Что такое паттерн Decorator?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерн Decorator
Decorator (Декоратор) — это структурный паттерн проектирования, который позволяет динамически добавлять новые обязанности объектам, оборачивая их в специальные обёртки. Это альтернатива наследованию, которая позволяет избежать создания множества подклассов для комбинирования функциональности.
Основная идея
Вместо создания новых классов через наследование, мы оборачиваем исходный объект в объект-декоратор, который реализует тот же интерфейс, но добавляет новую функциональность. Это делается во время выполнения программы, без изменения кода клиента.
Проблема, которую решает Decorator
Представьте, что нужно добавить различные расширения к классу (логирование, кэширование, сжатие и т.д.):
// Плохо: взрывное количество комбинаций
class DataStream { }
class LoggingDataStream extends DataStream { }
class CachingDataStream extends DataStream { }
class LoggingCachingDataStream extends DataStream { }
class CompressingLoggingCachingDataStream extends DataStream { }
// ... и так далее
Правильное решение с Decorator
1. Базовый интерфейс:
public interface DataStream {
String read();
void write(String data);
}
2. Конкретная реализация:
public class FileDataStream implements DataStream {
@Override
public String read() {
return "Data from file";
}
@Override
public void write(String data) {
System.out.println("Writing to file: " + data);
}
}
3. Абстрактный декоратор:
public abstract class DataStreamDecorator implements DataStream {
protected DataStream wrappedStream;
public DataStreamDecorator(DataStream stream) {
this.wrappedStream = stream;
}
@Override
public String read() {
return wrappedStream.read();
}
@Override
public void write(String data) {
wrappedStream.write(data);
}
}
4. Конкретные декораторы:
// Логирование
public class LoggingDecorator extends DataStreamDecorator {
public LoggingDecorator(DataStream stream) {
super(stream);
}
@Override
public String read() {
System.out.println("[LOG] Reading data");
return wrappedStream.read();
}
@Override
public void write(String data) {
System.out.println("[LOG] Writing: " + data);
wrappedStream.write(data);
}
}
// Кэширование
public class CachingDecorator extends DataStreamDecorator {
private String cache;
public CachingDecorator(DataStream stream) {
super(stream);
}
@Override
public String read() {
if (cache == null) {
cache = wrappedStream.read();
}
return cache;
}
@Override
public void write(String data) {
cache = null;
wrappedStream.write(data);
}
}
// Сжатие
public class CompressionDecorator extends DataStreamDecorator {
public CompressionDecorator(DataStream stream) {
super(stream);
}
@Override
public String read() {
String data = wrappedStream.read();
return decompress(data);
}
@Override
public void write(String data) {
String compressed = compress(data);
wrappedStream.write(compressed);
}
private String compress(String data) {
return "[COMPRESSED]" + data;
}
private String decompress(String data) {
return data.replace("[COMPRESSED]", "");
}
}
5. Использование:
// Создаём базовый поток
DataStream stream = new FileDataStream();
// Добавляем логирование
stream = new LoggingDecorator(stream);
// Добавляем кэширование
stream = new CachingDecorator(stream);
// Добавляем сжатие
stream = new CompressionDecorator(stream);
// Используем как обычный объект
String data = stream.read();
stream.write("Hello, World!");
Реальные примеры в Java
Потоки ввода-вывода:
InputStream input = new FileInputStream("file.txt");
input = new BufferedInputStream(input); // Буферизация
input = new DataInputStream(input); // Дополнительная функциональность
Collections.unmodifiable:
List<String> list = new ArrayList<>();
List<String> unmodifiable = Collections.unmodifiableList(list);
// unmodifiable — это декоратор, который оборачивает list
Преимущества и недостатки
Преимущества:
- Гибкость: добавляем функциональность без изменения исходного кода
- Комбинируемость: легко комбинировать несколько декораторов
- Соответствие принципу Open/Closed: открыт для расширения, закрыт для модификации
Недостатки:
- Может привести к большому количеству мелких классов
- Порядок декораторов иногда имеет значение
- Сложнее отладить, чем обычное наследование
Decorator — мощный паттерн для добавления динамической функциональности без нарушения принципов SOLID.