//предназначен для динамического подключения дополнительного поведения к объекту abstract class Beverage { double get cost; String get ingredients; } class Ingredient { double cost; String name; Ingredient(this.name, this.cost); @override String toString() => this.name; } var coffee = Ingredient("кофе", .25); var milk = Ingredient("молоко", .5); var sugar = Ingredient("сахар", .1); class Coffee implements Beverage { Set _ingredients = Set.from([coffee, milk, sugar]); double get cost => _ingredients.fold(0, (total, i) => total + i.cost); String get ingredients { var stringIngredients = _ingredients.fold("", (String str, i) => str + "${i.name}, "); var trimmedString = stringIngredients.substring(0, stringIngredients.length - 2); var lastComma = trimmedString.lastIndexOf(","); var replacement = ",".allMatches(trimmedString).length > 1 ? ", и" : " и"; return trimmedString.replaceRange(lastComma, lastComma + 1, replacement); } } class PremiumCoffeDecorator implements Beverage { Beverage _coffee = Coffee(); double get cost => _coffee.cost * 5; String get ingredients => _coffee.ingredients; } void main() { var coffee = Coffee(); var premCoffee = PremiumCoffeDecorator(); print( "Обычное кофе состоит из ${coffee.ingredients}. Оно стоит \$${coffee.cost}"); print( "Лучшее кофе состоит из ${premCoffee.ingredients}. Оно стоит \$${premCoffee.cost}"); // Coffee contains coffee, milk, and sugar. It costs $0.85 // Starbucks coffee contains coffee, milk, and sugar. It costs $4.25 }