Design Patterns(GoF - Gang of Four)

Проработать

  1. Шаблоны проектирования Java
  2. 8 Design Patterns EVERY Developer Should Know
  3. Bruce Eckel - Thinking in Patterns with Java

Что это

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

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

  1. Factory Method(Фабричный метод) - определяет общий интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов.
  2. 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();
        }
    }
            
  3. Abstract Factory(Абстрактная фабрика) - позволяет создавать семейства связанных объектов, не привязываясь к конкретным классам создаваемых объектов.
  4. 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
            
  5. Builder(Строитель) - позволяет создавать сложные объекты пошагово. Убирает необходимость создавать множество конструкторов.
  6. Prototype(Прототип) - позволяет копировать объекты, не вдаваясь в подробности их реализации.
  7. Singleton(Одиночка) - гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. Есть 2 варианта создания 1 - Lazy(создание при обращении), 2 - Eager(жадный, создание при старте приложения).
  8. Пример:

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

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

  1. Adapter(Адаптер) - позволяет объектам с несовместимыми интерфейсами работать вместе.
  2. Bridge(Мост) - разделяет один или несколько классов на две отдельные иерархии — абстракцию и реализацию, позволяя изменять их независимо друг от друга.
  3. Composite(Компоновщик) - позволяет сгруппировать множество объектов в древовидную структуру, а затем работать с ней так, как будто это единичный объект.
  4. Flyweight(Легковес) - позволяет вместить большее количество объектов в отведённую оперативную память. Легковес экономит память, разделяя общее состояние объектов между собой, вместо хранения одинаковых данных в каждом объекте.
  5. Facade(Фасад) - предоставляет простой интерфейс к сложной системе классов, библиотеке или фреймворку.
  6. Decorator(Wrapper)(Декоратор) - позволяет динамически добавлять объектам новую функциональность, оборачивая их в полезные «обёртки». Гибкая альтернатива практике создания подклассов с целью расширения функциональности. Примеры:InputStream, FileInputStream, BufferedReader и тд.
  7. Proxy(Заместитель) - позволяет подставлять вместо реальных объектов специальные объекты-заменители. Эти объекты перехватывают вызовы к оригинальному объекту, позволяя сделать что-то до или после передачи вызова оригиналу.

Сравнение Adapter, Decorator и Proxy?

Заместитель(proxy) оборачивает некоторый класс и предоставляет такой же интерфейс. Цель -- "притвориться" оригинальным классом и скрыть от клиента детали.

Декоратор также оборачивает некоторый класс и предоставляет такой же или расширенный интерфейс. Т.е. декоратор может притворяться оригинальным классом и при этом расширять его функциональность. Пример: у вас есть заместитель, который прячет вызовы к стороннему сервису. Можно создать декоратор, который будет оборачивать и кэшировать результаты вызовов. Другой пример: нужно расширить функциональность оригинального класса, но он закрыт для наследования. Создается декоратор, который расширяет интерфейс оригинального класса.

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

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

  1. Chain of Responsibility(Цепочка обязанностей) - позволяет передавать запросы последовательно по цепочке обработчиков. Каждый последующий обработчик решает, может ли он обработать запрос сам и стоит ли передавать запрос дальше по цепи.
  2. Command(Команда) - превращает запросы в объекты, позволяя передавать их как аргументы при вызове методов, ставить запросы в очередь, логировать их, а также поддерживать отмену операций.
  3. Iterator(Итератор) - даёт возможность последовательно обходить элементы составных объектов, не раскрывая их внутреннего представления.
  4. Mediator(Посредник) - позволяет уменьшить связанность множества классов между собой, благодаря перемещению этих связей в один класс-посредник.
  5. Memento(Снимок) - позволяет сохранять и восстанавливать прошлые состояния объектов, не раскрывая подробностей их реализации.
  6. Observer(Наблюдатель) - создаёт механизм подписки, позволяющий одним объектам следить и реагировать на события, происходящие в других объектах.
  7. State(Состояние) - позволяет объектам менять поведение в зависимости от своего состояния. Извне создаётся впечатление, что изменился класс объекта.
  8. Strategy(Стратегия) - определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения программы.
  9. Template Method(Шаблонный метод) - скелет алгоритма, перекладывая ответственность за некоторые его шаги на подклассы. Паттерн позволяет подклассам переопределять шаги алгоритма, не меняя его общей структуры.
  10. Visitor(Посетитель) - позволяет добавлять в программу новые операции, не изменяя классы объектов, над которыми эти операции могут выполняться.