Design Patterns(GoF - Gang of Four)

Проработать

  1. Шаблоны проектирования Java
  2. 8 Design Patterns EVERY Developer Should Know
  3. Bruce Eckel - Thinking in Patterns with Java
  4. Decorator (Проблематика), Dependency Inversion, UML/OOP зв'язки, T/S
  5. 7 Design Patterns EVERY Developer Should Know
  6. Decorator

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

Что это

Паттерны проектирования - шаблоны проектирования программного обеспечения.

Creational(Порождающие) - удобное и безопасное создание новых объектов или семейств объектов.

Factory Method(Фабричный метод)

Определяет общий интерфейс для создания объектов в superclass, позволяя подклассам изменять тип создаваемых объектов.

Реализация: метод create(String type) возвращает нужный подкласс

Пример: parsers файлов(.json, .xml), отправка уведомлений

class A {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();
    }

    protected Foo makeFoo() {
        return new RegularFoo();
    }
}

class B extends A {
    protected Foo makeFoo() {
        //subclass is overriding the factory method
        //to return something different
        return new SpecialFoo();
    }
}
        

Abstract Factory(Абстрактная фабрика)

Позволяет создавать семейства связанных объектов, не привязываясь к конкретным классам создаваемых объектов.

Реализация: интерфейс для создания связанных объектов без указания их классов.

Пример: UI-темы (тёмная/светлая), фабрики виджетов операционной системы.

class A {
    private Factory factory;

    public A(Factory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        //The concrete class of "f" depends on the concrete class
        //of the factory passed into the constructor. If you provide a
        //different factory, you get a different Foo object.
        Foo f = factory.makeFoo();
        f.whatever();
    }
}

interface Factory {
    Foo makeFoo();
    Bar makeBar();
    Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}

//need to make concrete factories that implement the "Factory" interface here
        

Builder(Строитель)

Позволяет создавать сложные объекты пошагово. Убирает необходимость создавать множество конструкторов.

Реализация: цепочка вызовов .set() + .build().

Пример: создание сложных объектов, например HTTP-запросов.

Prototype(Прототип)

Позволяет копировать объекты, не вдаваясь в подробности их реализации.

\

Реализация: клонирование существующего объекта через .clone().

Пример: игровые персонажи, шаблоны документов, клоны интерфейсов.

Singleton(Одиночка)

Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. Есть 2 варианта создания 1 - Lazy(создание при обращении), 2 - Eager(жадный, создание при старте приложения).

Реализация: статический экземпляр + приватный конструктор.

Пример: логгер, менеджер конфигурации, пул подключений к БД.

class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
        

Structural(Структурные) - построение удобных в поддержке иерархий классов.

Adapter(Адаптер)

Изменение интерфейса. Позволяет объектам с несовместимыми интерфейсами работать вместе.

Реализация: класс-обёртка, преобразующий интерфейс.

Пример: интеграция с легаси API, InputStreamReader.

Bridge(Мост)

Разделяет один или несколько классов на две отдельные иерархии — абстракцию и реализацию, позволяя изменять их независимо друг от друга.

Реализация: разделение абстракции и реализации.

Пример: представление UI → движок отрисовки (SVG, Canvas и т.д.).

Composite(Компоновщик)

Позволяет сгруппировать множество объектов в древовидную структуру, а затем работать с ней так, как будто это единичный объект.

Реализация: древовидная структура, где элементы и группы обрабатываются одинаково.

Пример: иерархия файлов и папок, UI-компоненты.

Flyweight(Легковес)

Позволяет вместить большее количество объектов в отведённую оперативную память. Легковес экономит память, разделяя общее состояние объектов между собой, вместо хранения одинаковых данных в каждом объекте.

Реализация: повторное использование объектов с общим внутренним состоянием.

Пример: глифы шрифта, иконки интерфейса, текстуры в играх.

Facade(Фасад)

Предоставляет простой интерфейс к сложной системе class/library/framework.

Реализация: один класс делегирует вызовы нескольким подсистемам.

Пример: java.util.logging, фасад медиаплеера.

Decorator(Wrapper)(Декоратор)

Добавить новую функциональность(не меняя базовый интерфейс). Добавлять объектам новую функциональность, о борачивая их в полезные «обёртки». Гибкая альтернатива практике создания подклассов с целью расширения функциональности. Примеры:InputStream, FileInputStream, BufferedReader и тд. Способствует SOLID - Open Close.

Реализация: обёртка над объектом + добавление поведения на лету

Пример: логгирование, сжатие, кэширование

Proxy(Заместитель)

Контроль доступа, защита, управление ресурсами. Эти объекты перехватывают вызовы к оригинальному объекту, позволяя сделать что-то до или после передачи вызова оригиналу.

Реализация: обёртка над реальным объектом для контроля доступа или производительности.

Пример: ленивая загрузка, контроль доступа, удалённые прокси.

Behavioral(Поведенческие) - эффективного и безопасного взаимодействия между объектами программы.

Chain of Responsibility(Цепочка обязанностей)

Позволяет передавать запросы последовательно по цепочке обработчиков. Каждый последующий обработчик решает, может ли он обработать запрос сам и стоит ли передавать запрос дальше по цепи.

Реализация: каждый обработчик решает — обработать или передать дальше.

Пример: эскалация тикетов в техподдержке, всплытие событий (event bubbling).

Command(Команда)

Превращает запросы в объекты, позволяя передавать их как аргументы при вызове методов, ставить запросы в очередь, логировать их, а также поддерживать отмену операций.

Реализация: инкапсуляция действия в объект с методом execute().

Пример: Undo/Redo, обработка нажатий кнопок.

Iterator(Итератор)

Даёт возможность последовательно обходить элементы составных объектов, не раскрывая их внутреннего представления.

Mediator(Посредник)

Позволяет уменьшить связанность множества классов между собой, благодаря перемещению этих связей в один класс-посредник.

Реализация: центральный объект управляет взаимодействием компонентов.

Пример: менеджер чата, валидация форм в UI.

Memento(Снимок)

Позволяет сохранять и восстанавливать прошлые состояния объектов, не раскрывая подробностей их реализации.

Реализация: сохранение и восстановление внутреннего состояния объекта.

Пример: история изменений, снапшоты состояния в текстовом редакторе.

Observer(Наблюдатель)

Создаёт механизм подписки, позволяющий одним объектам следить и реагировать на события, происходящие в других объектах.

Реализация: список подписчиков + цикл notifyAll().

Пример: система событий, UI-слушатели, подписки на YouTube.

State(Состояние)

Позволяет объектам менять поведение в зависимости от своего состояния. Извне создаётся впечатление, что изменился класс объекта.

Реализация: поведение определяется текущим объектом состояния.

Пример: состояния медиаплеера — воспроизведение/пауза/стоп.

Strategy(Стратегия)

Определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения программы.

Реализация: интерфейс + метод setStrategy()

Пример: алгоритмы сортировки, платёжные процессоры

Template Method(Шаблонный метод)

Скелет алгоритма, перекладывая ответственность за некоторые его шаги на подклассы. Паттерн позволяет подклассам переопределять шаги алгоритма, не меняя его общей структуры.

Реализация: базовый класс задаёт общий алгоритм, подклассы переопределяют шаги.

Пример: обработка онлайн-заказа — оплата → подтверждение → доставка.

Visitor(Посетитель)

Позволяет добавлять в программу новые операции, не изменяя классы объектов, над которыми эти операции могут выполняться.

Реализация: внешний класс выполняет операции над элементами структуры

Пример: обход файловой системы, обработка AST