Паттерн проектирования декоратор позволяет нам динамически добавлять функциональность объекту без влияния на поведение объектов того же самого класса. Звучит несколько запутанно, но когда увидите код все станет понятнее.
Особенности
— Декоратор позволяет добавлять функциональность существующему объекту без изменения его структуру, то есть исходный класс не меняется
— Паттерн проектирования декоратор — это структурный паттерн, который обеспечивает обертку для существующего класса
— Создаются классы-декораторы, которые оборачивают исходный класс и предоставляют дополнительную функциональность, сохраняя сигнатуры методов исходного класса нетронутыми
— Паттерн проектирования декоратор чаще всего используется для следования принципу единой ответственности (single responsibility из SOLID), поскольку мы не нагружаем исходный класс дополнительными обязанностями, а разделяем их на классы-декораторы
— Декоратор структурно почти аналогичен паттерну «цепочка ответственности» (chain of responsibility)
Необходимо учитывать следующие ключевые моменты
— Декоратор полезен для возможности модифицировать поведение объекта во время рантайма. Такой код легко поддерживать и расширять.
— Недостатком этого паттерна является то, что используется большое количество однотипных объектов-декораторов
— Паттерн декоратор часто используется в классах Java IO (FileReader, BufferedReader и т. д.)
Что сделаем
— Создадим интерфейс
— Создадим конкретные реализации этого интерфейса
— Создадим абстрактный декоратор, реализующий этот интерфейс
— Создадим конкретный декоратор, наследующийся от абстрактного декоратора
— Используем конкретный декоратор для "декорирования" конкретных реализаций интерфейса
Реализация:
Мы создадим интерфейс Shape и конкретные классы, реализующие этот интерфейс. Затем мы создадим абстрактный класс-декоратор ShapeDecorator, реализующий интерфейс Shape и имеющий объект Shape в качестве поля класса.
— Shape — имя интерфейса
— Классы Rectangle, Triangle и класс Circle будут конкретными классами, реализующими интерфейс Shape
— ShapeDecorator — это абстрактный класс-декоратор, реализующий тот же интерфейс Shape
— RedShapeDecorator — конкретный класс, реализующий ShapeDecorator
— Demo — демонстрационный класс, в котором мы будем использовать RedShapeDecorator для декорирования объектов Shape
Шаг 1: создаем интерфейс Shape

public interface Shape {
void draw();
}
Шаг 2: создадим несколько реализаций этого интерфейса. В примере ниже будет только круг, а по факту создадим еще парочку: прямоугольник и треугольник.
public class Circle implements Shape{
@Override
public void draw() {
System.out.println("Я круг!");
}
}
Шаг 3: создадим абстрактный декоратор, реализующий интерфейс Shape
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
//Конструктор, принимающий объект Shape
public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape;
}
public void draw() {
decoratedShape.draw();
}
}
Шаг 4: создадим конкретный класс-декоратор, наследующийся от абстрактного класса
public class RedShapeDecorator extends ShapeDecorator{
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape) {
System.out.println("Сообщение от RedShapeDecorator. Цвет границы: красный");
}
}
Шаг 5: используем RedShapeDecorator чтобы раскрасить наши объекты
public class Demo {
public static void main(String[] args)
{
Shape circle = new Circle();
Shape redCircle= new RedShapeDecorator(new Circle());
Shape redRectangle= new RedShapeDecorator(new Rectangle());
Shape redTriangle = new RedShapeDecorator(new Triangle());
System.out.println("\nОбычный круг:");
circle.draw();
System.out.println("\nКруг с красной границей:");
redCircle.draw();
System.out.println("\nПрямоугольник с красной границей:");
redRectangle.draw();
System.out.println("\nТреугольник с красной границей:");
redTriangle.draw();
}
}
Шаг 6: смотрим в консоль и радуемся
Обычный круг:
Я круг!
Круг с красной границей:
Я круг!
Сообщение от RedShapeDecorator. Цвет границы: красный
Прямоугольник с красной границей:
Я прямоугольник!
Сообщение от RedShapeDecorator. Цвет границы: красный
Треугольник с красной границей:
Я треугольник!
Сообщение от RedShapeDecorator. Цвет границы: красный
Разобрав на примере паттерн проектирования декоратор, можно сделать вывод, что его использование оправдано в следующих случаях:
— Когда мы хотим добавить, улучшить или, возможно, удалить поведение или состояние объекта
— Когда мы просто хотим изменить функциональность одного конкретного объекта класса, а остальные оставить без изменений
Спасибо!
Репозиторий с файлами проекта
За основу взята статья с сайта geeksforgeeks.org
Мой блог начинающего Java Dev
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ