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
Абстрактному классу ShapeDecorator не нужно реализовывать интерфейс Shape - достаточно того, что этот абстрактный класс содержит поле Shape.
Dmitry B Уровень 20
22 июля 2022
Подскажите, пожалуйста, что за алгоритмическая нотация на картинке?
Макс Дудин Уровень 41
2 июля 2022
Ну ok, thanks .... всё понятно и вроде не сложно, пошёл решать задачку