Паттерн "Декоратор" (Decorator) в Java — расширение поведения без наследования
Обзор — в структурных паттернах. Здесь — практический Decorator на Java через слой логирования и слой кеша.
Задача паттерна
Decorator добавляет поведение объекту в runtime без изменения его класса.
Идея простая: объект оборачивается в другой объект с тем же интерфейсом. Каждый слой может добавить логику до/после делегирования.
Пример — сервис данных
import java.util.HashMap;
import java.util.Map;
interface DataService {
String getData(String key);
}
class DatabaseService implements DataService {
@Override
public String getData(String key) {
return "data_from_db_" + key;
}
}
abstract class DataServiceDecorator implements DataService {
protected final DataService delegate;
protected DataServiceDecorator(DataService delegate) {
this.delegate = delegate;
}
}
class LoggingDecorator extends DataServiceDecorator {
LoggingDecorator(DataService delegate) {
super(delegate);
}
@Override
public String getData(String key) {
System.out.println("LOG: запрос " + key);
String result = delegate.getData(key);
System.out.println("LOG: ответ получен");
return result;
}
}
class CachingDecorator extends DataServiceDecorator {
private final Map<String, String> cache = new HashMap<>();
CachingDecorator(DataService delegate) {
super(delegate);
}
@Override
public String getData(String key) {
return cache.computeIfAbsent(key, delegate::getData);
}
}
DataService service = new CachingDecorator(
new LoggingDecorator(
new DatabaseService()
)
);
service.getData("user:42"); // лог + БД + кеш
service.getData("user:42"); // кеш
Когда использовать
| Сигнал | Почему Decorator |
|---|---|
| Комбинации поведения заранее неизвестны | Слои добавляются и переставляются |
| Нежелательно раздувать иерархию наследования | Избегаем ServiceWithLogAndCacheAndMetrics |
| Нужно расширять в runtime | Новая обертка подключается конфигурацией |
В JDK тот же принцип в I/O: InputStream -> BufferedInputStream -> GZIPInputStream.
Decorator и Proxy
| Decorator | Proxy | |
|---|---|---|
| Назначение | Расширение поведения | Контроль доступа и жизненного цикла |
| Фокус | Дополнительные возможности | Проверка прав, lazy, удаленный вызов |
Практика Proxy на Java — 128.
Риски
Много мелких классов и сложный стек оберток в отладке. Держите прозрачные имена (CachingDecorator, MetricsDecorator) и фиксируйте порядок в конфигурации.
См. также
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Паттерн — это повторяющийся шаблон, узор или схема. Паттерны встречаются повсюду — в природе, архитектуре, поведении людей и, конечно, в программировании. Порождающие паттерны проектирования — это группа шаблонов, направленных на решение задач, связанных с созданием объектов. Структурные паттерны — это группа шаблонов проектирования, решающих задачи организации классов и объектов таким образом, чтобы обеспечить гибкую архитектуру программного обеспечения. Поведенческие паттерны — это группа шаблонов проектирования, которые определяют способы взаимодействия объектов и распределения ответственности между ними. Архитектурные паттерны — это проверенные решения для организации структуры программного обеспечения. Интеграция систем — одна из центральных задач в современной разработке программного обеспечения. Паттерны доменного моделирования представляют собой проверенные решения для организации бизнес-логики в программных системах. Паттерн Strategy в C# — классическая реализация через интерфейс, замена на Func и Action, DI и критерии выбора без лишних абстракций. Паттерн Iterator в C# — ручной IEnumerator, генерация итератора компилятором через yield return, ленивость, LINQ и случаи, когда класс писать всё же нужно. Abstract Factory в C# и .NET — классическая схема через интерфейсы, замена через DI-контейнер, фабричный делегат и keyed services в .NET 8. Паттерн Command в C# — классическая схема, делегаты, MediatR, очередь задач, undo и критерии выбора между объектом команды и простым вызовом сервиса. Паттерн Observer в C# — event и делегаты, IObservable IObserver, слабая связанность, отписка и как не поймать утечки памяти в долгоживущих сервисах.Обзор паттернов проектирования
Порождающие паттерны
Структурные паттерны
Поведенческие паттерны
Архитектурные паттерны
Паттерны интеграции внешних систем
Паттерны проектирования доменных моделей
Стратегия в C#
Итератор в C#
Фабрика в C#
Команда в C#
Наблюдатель в C#