Ответ
Паттерн Декоратор (Decorator) — это структурный паттерн проектирования, который позволяет динамически добавлять новую функциональность объектам, оборачивая их в объекты-декораторы. Он предоставляет гибкую альтернативу наследованию для расширения поведения.
Ключевой принцип: Композиция предпочтительнее наследования. Декоратор реализует тот же интерфейс, что и оборачиваемый компонент, и делегирует ему основную работу, добавляя что-то своё до или после вызова.
Участники:
- Компонент (Component): Общий интерфейс для декорируемых объектов и декораторов.
- Конкретный компонент (Concrete Component): Базовая реализация, которую мы будем декорировать.
- Декоратор (Decorator): Абстрактный класс, реализующий интерфейс Component и содержащий ссылку на него.
- Конкретный декоратор (Concrete Decorator): Добавляет конкретную функциональность.
Классический пример: Система оповещений.
// 1. Компонент - общий интерфейс
interface Notifier {
String send(String message);
}
// 2. Конкретный компонент - базовая реализация
class SimpleNotifier implements Notifier {
@Override
public String send(String message) {
return "Sending basic notification: " + message;
}
}
// 3. Базовый декоратор (может быть абстрактным)
abstract class NotifierDecorator implements Notifier {
protected Notifier wrappedNotifier; // Ссылка на оборачиваемый компонент
public NotifierDecorator(Notifier notifier) {
this.wrappedNotifier = notifier;
}
@Override
public String send(String message) {
return wrappedNotifier.send(message); // Делегирование
}
}
// 4. Конкретные декораторы
class SMSDecorator extends NotifierDecorator {
public SMSDecorator(Notifier notifier) {
super(notifier);
}
@Override
public String send(String message) {
// 1. Вызываем поведение обёрнутого объекта
String baseResult = super.send(message);
// 2. Добавляем своё поведение
return baseResult + "n -> Also sending SMS: " + message;
}
}
class FacebookDecorator extends NotifierDecorator {
public FacebookDecorator(Notifier notifier) {
super(notifier);
}
@Override
public String send(String message) {
return super.send(message) + "n -> Also posting to Facebook: " + message;
}
}
// 5. Клиентский код
public class Client {
public static void main(String[] args) {
Notifier notifier = new SimpleNotifier(); // База
notifier = new SMSDecorator(notifier); // Добавили SMS
notifier = new FacebookDecorator(notifier); // Добавили Facebook
System.out.println(notifier.send("Server is down!"));
}
}
/* Вывод:
Sending basic notification: Server is down!
-> Also sending SMS: Server is down!
-> Also posting to Facebook: Server is down!
*/
Преимущества:
- Гибкость: Поведение объекта можно собирать динамически во время выполнения.
- Соблюдение OCP (Open/Closed Principle): Можно добавлять новую функциональность, не изменяя существующий код.
- Избегание взрывного роста классов: Вместо создания классов
SMSNotifier,FacebookNotifier,SMSAndFacebookNotifierи т.д. используется композиция.
Пример в Java Standard Library: Классы java.io.BufferedInputStream, java.io.DataInputStream являются декораторами для InputStream.
Ответ 18+ 🔞
А, паттерн Декоратор, ёпта! Ну это ж классика, блядь, как «Муму» Тургенева, только про код, а не про собак. Слушай сюда, я тебе сейчас на пальцах объясню, чтобы даже мартышлюшка поняла.
Представь, у тебя есть объект. Простой, как три копейки. Ну, допустим, нотификатор, который только в консоль пишет. И тут тебе начальство говорит: «А добавь-ка, дружок, ещё и смс-ки слать». Ты такой: «Окей, наследуем класс, делаем SMSNotifier». А потом: «А ещё в телегу!». Ты опять наследуешь. Потом: «А можно смс и в телегу, но без консоли?». И тут ты понимаешь, что у тебя уже овердохуища классов: SMSAndTelegramNotifier, ConsoleAndSMSNotifier, TelegramOnlyNotifier... Пиздец, блядь, терпения ноль ебать! Это ж как Герасима заставить все комбинации собак топить — нихуя не масштабируется.
Вот тут-то и выходит на сцену наш герой — Декоратор. Хитрый, как жопа с ручками. Его главная фишка — он не наследует функциональность, а оборачивает объект, как капустный лист голубцы, и добавляет сверху свой соус.
Как это работает, блядь?
- Компонент (Component) — это интерфейс, общий для всех. Как договор: «Все, кто хочет быть нотификатором, должны уметь
send(message)». Без этого нихуя. - Конкретный компонент (Concrete Component) — это наш простой, честный работяга, который делает базовую работу.
SimpleNotifier, который только в консоль пишет. Немой, как Герасим, но своё дело знает. - Декоратор (Decorator) — это абстрактная обёртка. Она тоже умеет
send(message), но внутри у неё сидит ссылка на другойNotifier(который она оборачивает). Её методsend— это просто передача эстафеты дальше, обёрнутому объекту. Пока без своей фишки. - Конкретный декоратор (Concrete Decorator) — вот где магия! Это уже обёртка с характером. Она вызывает
sendу того, кого оборачивает, а до или после этого делает свою, ебучую, работу. Отправить смс, запостить в фейсбук, нахуй послать — что угодно.
Смотри, как это в коде выглядит, ядрёна вошь:
// 1. Интерфейс-договор. Все должны уметь send.
interface Notifier {
String send(String message);
}
// 2. Честный работяга. Базовая реализация.
class SimpleNotifier implements Notifier {
@Override
public String send(String message) {
return "Sending basic notification: " + message; // Просто в консоль, по старинке
}
}
// 3. Абстрактная обёртка-посредник.
abstract class NotifierDecorator implements Notifier {
protected Notifier wrappedNotifier; // Ссылка на того, кого оборачиваем. Сердце паттерна!
public NotifierDecorator(Notifier notifier) {
this.wrappedNotifier = notifier; // Запоминаем, кого будем декорировать
}
@Override
public String send(String message) {
// Просто передаём вызов дальше, по цепочке
return wrappedNotifier.send(message);
}
}
// 4. А вот и конкретные декораторы с прибамбасами!
class SMSDecorator extends NotifierDecorator {
public SMSDecorator(Notifier notifier) {
super(notifier); // Говорим: "Оберни-ка вот этого чувака"
}
@Override
public String send(String message) {
// 1. Сначала дай отработать тому, кого я обёртываю
String baseResult = super.send(message);
// 2. А теперь моя, епта, фишка!
return baseResult + "n -> Also sending SMS: " + message;
}
}
class FacebookDecorator extends NotifierDecorator {
public FacebookDecorator(Notifier notifier) {
super(notifier);
}
@Override
public String send(String message) {
// Можно и так: добавить своё ДО вызова обёрнутого объекта
// System.out.println("Подготавливаю пост для Facebook...");
return super.send(message) + "n -> Also posting to Facebook: " + message;
}
}
А теперь клиентский код, где мы собираем эту франкенштейн-сборку:
public class Client {
public static void main(String[] args) {
// Начинаем с простого нотификатора
Notifier notifier = new SimpleNotifier(); // Просто консоль
System.out.println("--- Только база ---");
System.out.println(notifier.send("Пинг"));
// Оборачиваем его в SMS-декоратор. Теперь это консоль + SMS.
notifier = new SMSDecorator(notifier);
System.out.println("n--- База + SMS ---");
System.out.println(notifier.send("Пинг"));
// Оборачиваем результат ещё раз, в Facebook-декоратор. Теперь это консоль + SMS + Facebook.
notifier = new FacebookDecorator(notifier);
System.out.println("n--- База + SMS + Facebook (ВОТ ЭТО ПИЗДЕЦ!) ---");
System.out.println(notifier.send("Server is down!"));
}
}
Вывод будет, блядь, предсказуемый и красивый:
--- Только база ---
Sending basic notification: Пинг
--- База + SMS ---
Sending basic notification: Пинг
-> Also sending SMS: Пинг
--- База + SMS + Facebook (ВОТ ЭТО ПИЗДЕЦ!) ---
Sending basic notification: Server is down!
-> Also sending SMS: Server is down!
-> Also posting to Facebook: Server is down!
В чём сила, брат?
- Гибкость, блядь, овердохуичная! Собрал комбинацию на лету, как лего. Хочешь только SMS и Facebook, но без консоли?
new FacebookDecorator(new SMSDecorator(new SimpleNotifier()))— и в рот меня чих-пых, готово! - Принцип открыт/закрыт (OCP) в действии. Хочешь новый тип уведомления (например, в Telegram)? Создаёшь новый класс
TelegramDecorator, и нихуя не ломаешь старый код. Красота! - Нет взрыва классов. Не нужно создавать
SMSAndFacebookNotifier,SMSAndTelegramNotifierи прочую хуйню. Всё через композицию.
Где это в жизни, блядь? Да везде! Классика — java.io. BufferedInputStream — это декоратор для FileInputStream. Он оборачивает его, добавляя буферизацию. DataInputStream — ещё один декоратор, добавляющий чтение примитивов. И все они — потомки InputStream. Элегантно, сука, как танк в балете.
Короче, Декоратор — это когда нужно динамически и прозрачно для клиента накрутить объекту функциональности, не плодя ебаный зоопарк наследников. Понял? Если нет — иди, перечитай, пока не дойдёт, а то я устал, как собака, объяснять.