Вопрос проверяет понимание паттерна проектирования 'Декоратор' и его применение для динамического добавления функциональности к объектам.
Паттерн 'Декоратор' (Decorator) — это структурный паттерн проектирования, который позволяет динамически добавлять новую функциональность объектам, оборачивая их в специальные объекты-декораторы. Вместо изменения исходного класса (что нарушает принцип открытости/закрытости), вы создаёте цепочку обёрток, каждая из которых добавляет своё поведение.
Декоратор реализует тот же интерфейс, что и оборачиваемый объект. При вызове метода декоратор выполняет дополнительную логику (до или после) и затем делегирует вызов обёрнутому объекту. Это позволяет комбинировать поведение на лету, создавая гибкие конфигурации.
// Базовый интерфейс компонента
interface Coffee {
cost(): number;
description(): string;
}
// Конкретный компонент
class SimpleCoffee implements Coffee {
cost() { return 5; }
description() { return 'Simple coffee'; }
}
// Базовый декоратор
abstract class CoffeeDecorator implements Coffee {
constructor(protected coffee: Coffee) {}
cost() { return this.coffee.cost(); }
description() { return this.coffee.description(); }
}
// Конкретные декораторы
class MilkDecorator extends CoffeeDecorator {
cost() { return super.cost() + 2; }
description() { return super.description() + ', milk'; }
}
class SugarDecorator extends CoffeeDecorator {
cost() { return super.cost() + 1; }
description() { return super.description() + ', sugar'; }
}
// Использование
let myCoffee: Coffee = new SimpleCoffee();
myCoffee = new MilkDecorator(myCoffee);
myCoffee = new SugarDecorator(myCoffee);
console.log(myCoffee.description()); // Simple coffee, milk, sugar
console.log(myCoffee.cost()); // 8Вывод: Используйте паттерн 'Декоратор', когда нужно гибко добавлять обязанности объектам во время выполнения, избегая жёсткой иерархии наследования и сохраняя код чистым и расширяемым.