JavaRush/Java блог/Java Developer/Паттерн проектирования декоратор с примерами
Sbv239
23 уровень

Паттерн проектирования декоратор с примерами

Статья из группы Java Developer
участников
Паттерн проектирования декоратор позволяет нам динамически добавлять функциональность объекту без влияния на поведение объектов того же самого класса. Звучит несколько запутанно, но когда увидите код все станет понятнее. Особенности — Декоратор позволяет добавлять функциональность существующему объекту без изменения его структуру, то есть исходный класс не меняется — Паттерн проектирования декоратор — это структурный паттерн, который обеспечивает обертку для существующего класса — Создаются классы-декораторы, которые оборачивают исходный класс и предоставляют дополнительную функциональность, сохраняя сигнатуры методов исходного класса нетронутыми — Паттерн проектирования декоратор чаще всего используется для следования принципу единой ответственности (single responsibility из SOLID), поскольку мы не нагружаем исходный класс дополнительными обязанностями, а разделяем их на классы-декораторы — Декоратор структурно почти аналогичен паттерну «цепочка ответственности» (chain of responsibility) Необходимо учитывать следующие ключевые моменты — Декоратор полезен для возможности модифицировать поведение объекта во время рантайма. Такой код легко поддерживать и расширять. — Недостатком этого паттерна является то, что используется большое количество однотипных объектов-декораторов — Паттерн декоратор часто используется в классах Java IO (FileReader, BufferedReader и т. д.) Что сделаем — Создадим интерфейс — Создадим конкретные реализации этого интерфейса — Создадим абстрактный декоратор, реализующий этот интерфейс — Создадим конкретный декоратор, наследующийся от абстрактного декоратора — Используем конкретный декоратор для "декорирования" конкретных реализаций интерфейса Реализация: Мы создадим интерфейс Shape и конкретные классы, реализующие этот интерфейс. Затем мы создадим абстрактный класс-декоратор ShapeDecorator, реализующий интерфейс Shape и имеющий объект Shape в качестве поля класса. Паттерн проектирования декоратор с примерами - 1 — 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
Комментарии (6)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Anonymous #2790769
Уровень 41
22 октября 2022, 10:19
Абстрактному классу ShapeDecorator не нужно реализовывать интерфейс Shape - достаточно того, что этот абстрактный класс содержит поле Shape.
Eduard
Уровень 41
14 февраля 2023, 15:57
Тогда это был бы не декоратор, а прокси
Роман
Уровень 30
25 июня 2023, 20:25
Если Абстрактный класс ShapeDecorator не будет наследовать Shape, то и его наследники типа RedShapeDecorator тоже не подхватят наследование интерфейса Shape, а тогда им нельзя будет дать ссылку типа Shape , это мое мнение
Dmitry B
Уровень 20
22 июля 2022, 08:45
Подскажите, пожалуйста, что за алгоритмическая нотация на картинке?
15 ноября 2023, 06:30
Это UML - диаграмма, показывает отношения между классами
Макс Дудин
Уровень 41
2 июля 2022, 15:20
Ну ok, thanks .... всё понятно и вроде не сложно, пошёл решать задачку