Паттерн Декоратор (Decorator Pattern) позволяет динамически добавлять новую функциональность объектам, оборачивая их в декораторы, не изменяя их структуру. Это альтернатива наследованию, которая обеспечивает большую гибкость. Декоратор имеет тот же интерфейс, что и декорируемый объект, и делегирует вызовы исходному объекту, добавляя свою логику до или после.
В примере ниже базовый класс Car может быть обернут декораторами AutoPilot и Spoiler, которые
добавляют дополнительные функции и изменяют поведение методов. Декораторы можно комбинировать в любом
порядке, создавая различные конфигурации объекта.
class Car {
constructor() {
this.price = 1500;
this.model = 'any Car you want';
}
getCarPrice() {
return this.price;
}
getCarModel() {
return this.model;
}
}
class Honda extends Car {
constructor() {
super();
this.price = 2500;
this.model = 'Honda Accord 2020';
}
}
// Декоратор для добавления автопилота
class AutoPilot {
constructor(car) {
this.car = car;
}
addAutoPilot() {
this.car.autopilot = true;
}
getCarPrice() {
return this.car.getCarPrice() + 5000;
}
getCarModel() {
return this.car.getCarModel();
}
getCarDescription() {
return `${this.car.getCarModel()} with autopilot`;
}
}
// Декоратор для добавления спойлера
class Spoiler {
constructor(car) {
this.car = car;
}
addSpoiler() {
this.car.spoiler = true;
}
getCarPrice() {
return this.car.getCarPrice() + 1000;
}
getCarModel() {
return this.car.getCarModel();
}
paintSpoiler(color = 'white') {
this.car.spoilerColor = color;
return this.car.spoilerColor;
}
getCarDescription() {
return `${this.car.getCarModel()} with spoiler`;
}
}
// Примеры использования
const basicHonda = new Honda();
console.log(basicHonda.getCarPrice()); // 2500
// Декорируем базовую Honda автопилотом
const hondaWithAutopilot = new AutoPilot(new Honda());
hondaWithAutopilot.addAutoPilot();
console.log(hondaWithAutopilot.getCarPrice()); // 7500
console.log(hondaWithAutopilot.getCarDescription()); // "Honda Accord 2020 with autopilot"
// Комбинируем декораторы: автопилот + спойлер
const hondaWithAutopilot2 = new AutoPilot(new Honda());
hondaWithAutopilot2.addAutoPilot();
const hondaWithAutopilotAndSpoiler = new Spoiler(hondaWithAutopilot2);
hondaWithAutopilotAndSpoiler.addSpoiler();
console.log(hondaWithAutopilotAndSpoiler.getCarPrice()); // 8500