Ответ
В Java декоратор — это структурный паттерн проектирования, который позволяет динамически добавлять объектам новую функциональность, оборачивая их в объекты-декораторы.
Пример:
interface Coffee {
double getCost();
String getDescription();
}
class SimpleCoffee implements Coffee {
public double getCost() { return 2.0; }
public String getDescription() { return "Simple Coffee"; }
}
class MilkDecorator implements Coffee {
private Coffee coffee;
public MilkDecorator(Coffee coffee) { this.coffee = coffee; }
public double getCost() { return coffee.getCost() + 0.5; }
public String getDescription() { return coffee.getDescription() + ", Milk"; }
}
Использование:
Coffee coffee = new MilkDecorator(new SimpleCoffee());
System.out.println(coffee.getDescription()); // "Simple Coffee, Milk"
System.out.println(coffee.getCost()); // 2.5
Декоратор сохраняет интерфейс исходного объекта и расширяет его поведение без наследования.
Ответ 18+ 🔞
А, декоратор! Ну это ж классика, ебать мои старые костыли. Представь себе ситуацию: есть у тебя объект, простой как три копейки. И вдруг тебе надо, чтобы он делал то же самое, но ещё и с перламутровыми пуговицами. Наследоваться? Да ну нахуй, это же жёсткая сцепка, потом от этого класса-урода все поломается.
Вот тут-то декоратор и выручает, хитрая жопа. Берёшь свой исходный объект, заворачиваешь его в другой объект, как в обёртку, и эта обёртка добавляет свою фишку. А главное — интерфейс остаётся тем же, все кто работал с простым объектом, будут работать и с обёрнутым, нихуя не заметив.
Смотри на примере кофе, тут всё понятно становится, ёпта.
interface Coffee {
double getCost();
String getDescription();
}
class SimpleCoffee implements Coffee {
public double getCost() { return 2.0; }
public String getDescription() { return "Simple Coffee"; }
}
class MilkDecorator implements Coffee {
private Coffee coffee;
public MilkDecorator(Coffee coffee) { this.coffee = coffee; }
public double getCost() { return coffee.getCost() + 0.5; }
public String getDescription() { return coffee.getDescription() + ", Milk"; }
}
Видишь, MilkDecorator? Он сам реализует Coffee, но в конструктор принимает тоже какой-то Coffee. Он не наследует SimpleCoffee, он его оборачивает. Внутри себя он вызывает методы того кофе, что ему передали, и добавляет сверху своё: цену молока и строчку в описание.
А теперь смотри, как это круто работает:
Coffee coffee = new MilkDecorator(new SimpleCoffee());
System.out.println(coffee.getDescription()); // "Simple Coffee, Milk"
System.out.println(coffee.getCost()); // 2.5
Создал простой кофе, обернул в декоратор молока — и получил новый объект. Хочешь ещё сироп? Без проблем! Оберни результат ещё в SyrupDecorator!
Coffee coffee = new SyrupDecorator(new MilkDecorator(new SimpleCoffee()));
Получится матрёшка, ёперный театр! Каждый декоратор добавляет свой функционал, и ты в любой момент можешь скомбинировать их как угодно, не создавая овердохуища классов вроде SimpleCoffeeWithMilkAndSyrupAndCinnamonAndWhippedCream.
Вот и весь фокус. Вместо того чтобы плодить наследников на каждый чих, ты создаёшь гибкие обёртки. Красота, да и только. Главное — не переборщить, а то наслоишь этих декораторов, что в итоге хуй с горы разберёшь, что там внутри и в каком порядке выполняется.