Design Patterns(GoF - Gang of Four)
    
    
        Что это
        Паттерны проектирования — шаблоны проектирования программного обеспечения.
    
    
        Creational(Порождающие) - Отвечают за удобное и безопасное создание новых объектов или семейств объектов.
        
            - Factory Method(Фабричный метод) - определяет общий интерфейс для создания объектов в суперклассе,
                позволяя подклассам изменять тип создаваемых объектов.
            
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(Абстрактная фабрика) - позволяет создавать семейства связанных объектов, не привязываясь
                к конкретным классам создаваемых объектов.
            
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(Строитель) - позволяет создавать сложные объекты пошагово. Убирает необходимость создавать
                множество конструкторов.
            
- Prototype(Прототип) - позволяет копировать объекты, не вдаваясь в подробности их реализации.
- 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(Адаптер) - изменение интерфейса. Позволяет объектам с несовместимыми интерфейсами работать вместе.
- Bridge(Мост) - разделяет один или несколько классов на две отдельные иерархии — абстракцию и реализацию,
                позволяя изменять их независимо друг от друга.
            
- Composite(Компоновщик) - позволяет сгруппировать множество объектов в древовидную структуру,
                а затем работать с ней так, как будто это единичный объект.
            
- Flyweight(Легковес) - позволяет вместить большее количество объектов в отведённую оперативную память.
                Легковес экономит память, разделяя общее состояние объектов между собой, вместо хранения одинаковых данных
                в каждом объекте.
            
- Facade(Фасад) - предоставляет простой интерфейс к сложной системе class/library/framework.
- Decorator(Wrapper)(Декоратор) - добавить новую функциональность(не меняя базовый интерфейс). Добавлять
                объектам новую функциональность, оборачивая их в полезные «обёртки». Гибкая альтернатива практике
                создания подклассов с целью расширения функциональности. Примеры:InputStream, FileInputStream,
                BufferedReader и тд. Способствует SOLID - Open Close.
            
- Proxy(Заместитель) - контроль доступа, защита, управление ресурсами. Эти объекты перехватывают вызовы
                к оригинальному объекту, позволяя сделать что-то до или после передачи вызова оригиналу.
            
Behavioral(Поведенческие) - Решают задачи эффективного и безопасного взаимодействия между объектами программы.
        
            - Chain of Responsibility(Цепочка обязанностей) - позволяет передавать запросы последовательно по цепочке
                обработчиков. Каждый последующий обработчик решает, может ли он обработать запрос сам и стоит ли передавать
                запрос дальше по цепи.
            
- Command(Команда) - превращает запросы в объекты, позволяя передавать их как аргументы при вызове методов,
                ставить запросы в очередь, логировать их, а также поддерживать отмену операций.
            
- Iterator(Итератор) - даёт возможность последовательно обходить элементы составных объектов,
                не раскрывая их внутреннего представления.
            
- Mediator(Посредник) - позволяет уменьшить связанность множества классов между собой, благодаря перемещению
                этих связей в один класс-посредник.
            
- Memento(Снимок) - позволяет сохранять и восстанавливать прошлые состояния объектов, не раскрывая
                подробностей их реализации.
            
- Observer(Наблюдатель) - создаёт механизм подписки, позволяющий одним объектам следить и реагировать
                на события, происходящие в других объектах.
            
- State(Состояние) - позволяет объектам менять поведение в зависимости от своего состояния. Извне создаётся
                впечатление, что изменился класс объекта.
            
- Strategy(Стратегия) - определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс,
                после чего алгоритмы можно взаимозаменять прямо во время исполнения программы.
            
- Template Method(Шаблонный метод) - скелет алгоритма, перекладывая ответственность за некоторые его шаги
                на подклассы. Паттерн позволяет подклассам переопределять шаги алгоритма, не меняя его общей структуры.
            
- Visitor(Посетитель) - позволяет добавлять в программу новые операции, не изменяя классы объектов,
                над которыми эти операции могут выполняться.