Design Pattern Documentation with Examples
Когда рассмотреть использование?
- Property Container - не знаешь, какие immutable property в будущем пригодятся, возможность добавлять любое свойство их в instance class через __construct()
- Delegation - есть несколько объектов с одинаковым поведением, позволяет переключать поведение используя общий интерфейс, через методы смены объекта
- Event Channel - взаимодействие издателей и подписчиков вне рамках самого канала, подписчик может отправлять и получать события
- Interface - абстрагирует какую-либо логику вызовом высокоуровневого интерфейса (например метод main() или run())
Порождающие - помогают абстрагироваться от прямого создания instance class (new ExampleClass()), основная идея создание похожих преднастроеных экземпляров классов
-
Abstract Factory (Инструментарий) - когда требуется предусмотреть некий переключатель (например переключатель тем), необходимо использовать переключатель конфигурации для группы объектов с одинаковым api (например переключение типа подключения к бд в PDO)
-
Factory Method - имеется вызов одинаковой последовательности действий над обьектом, но с разными классами, оптимизирует повторяющийся код
-
Static Factory - другой способ реализации простой или абстрактной фабрики. ($obj::build('factory-type'))
-
Simple Factory - вынести переключатель (switch/if) типа реализации (new Example()), способ абстрагирования от создания обьекта ($obj->build('factory-type'))
-
Singleton - необходимо исключить повторное создание экземпляра класса, класс не сохраняет состояние, нет property (например класс обработки логирования)
-
Multiton - выдать Singleton по ключу
-
Builder - много агрументов в __construct(), не все требуются при создании экземпряра класса (laravel QueryBuilder, doctrine Model), или есть логика которую можно преобразовать в декларативный подход (независимый от расположенения, вызов цепочки методов класса, возрощающий измененное состояние обьекта этого класса (пример Laravel Query Builder))
-
Lazy initialization - выполнение ресурсоемкой операции, по требованию, а не при инициализации класса (необязательные долгие операции при инцициализации класса)
-
Prototype - антипатрн для оптимизации, клонирование сложного обьекта, без создание его нового экземпляра через конструктор, есть возможность изменить оригинальный обьект, меняя клон
-
Оbject Pool - не применим в вебе
-
Adapter - поменялись названия методов, но функционал прежний.
-
Facade - цепочка вызовов классов, обьединение разных типов логики в один интерфейс, не должен сам содержать логики, только делегировать другим
-
Bridge - есть функционал который можно разделить на две независимые иерархии классов, абстракцию и реализацию
-
Composite - взаимодейсвие с иерархической группой обьектов также, как и с отдельно взятым экземпляром ( последовательный запуск общих методов для связзаных иерархий)
-
Decorator -наделить свои (или чужие) объекты новыми возможностями без модификации кода классов
-
Proxy -
- Observer
- Command - общий интерфейс (например очередь заданий), необходимо реализовать востановление преведущего состояние ( undo/ отмена назад, востановления после сбоя)
- Состояние
-
композиция - когда обьект создается внутри класса
-
агрегация - обьект создается снаружи и передается в класс (как аргумент)
- Абстракция -
- Инкапсуляция -
- Полиморфизм -
- Наследование -
- Инкапсулируйте то, что изменяется.
- Предпочитайте композицию наследованию.
- Программируйте на уровне интерфейсов.
- Стремитесь к слабой связанности взаимодействующих объектов. (агрегация)
- Классы должны быть открыты для расширения, но закрыты для изменения.
- Код должен зависеть от абстракций, а не от конкретных классов.
требует, чтобы высокоуровневые компоненты не зависели от низкоуровневых компонентов; вместо этого и те, и другие должны зависеть от абстракций
«Высокоуровневым» компонентом называется класс, поведение которого определяется в контексте других, «низкоуровневых» компонентов.
- Выделите аспекты приложения, которые могут изменяться, и отделите их от тех, которые всегда остаются постоянными.
Все паттерны обеспечивают возможность изменения некоторой части системы независимо от других частей.
Паттерны проектирования формируют единую номенклатуру для разработчиков. Когда вы овладеете этой номенклатурой, вам будет проще общаться с другими разработчиками — а у тех, кто паттернов не знает, появится лишний стимул для их изучения. Кроме того, вы начнете воспринимать архитектуру на более высоком уровне паттернов, а не на уровне объектов.
Номенклатуры паттернов обладают большой ВЫРАЗИТЕЛЬНОСТЬЮ. Используя паттерны в общении с другим разработчиком или группой, вы передаете не только название паттерна, но и целый набор характеристик, качеств и ограничений, представленных данным паттерном. Паттерны позволяют сказать больше меньшим количеством слов. Когда вы используете паттерн в описании, другие разработчики моментально понимают суть решения, о котором вы говорите.
Общение на уровне паттернов помогает дольше оставаться «на уровне архитектуры». Описание программной системы с использованием паттернов позволяет вести обсуждение на более абстрактном уровне, не отвлекаясь на второстепенные подробности реализации объектов и классов. Единая номенклатура повышает эффективность разработки. Группа, хорошо разбирающаяся в паттернах проектирования, быстрее продвигается вперед, а ее участники лучше понимают друг друга. Единые номенклатуры помогают новичкам разработчикам быстрее войти в курс дела. Новички берут пример с опытных разработчиков. Если опытный разработчик применяет паттерны в своей работе, у новичков появляются дополнительные стимулы для их использования. Создайте сообщество пользователей паттернов в своей организации.
Хорошие ОО-архитектуры хорошо расширяются, просты в сопровождении и пригодны для повторного использования.
Паттерны показывают, как строить системы с хорошими качествами ОО-проектирования.
Паттерны содержат проверенный опыт ОО-проектирования.
Паттерны образуют единую номенклатуру, которая повышает эффективность вашего общения с другими разработчиками.
Если два объекта могут взаимодействовать, не обладая практически никакой информацией друг о друге, такие объекты называют слабосвязанными.
Благодаря слабым связям мы можем вносить любые изменения на любой из двух сторон — при условии, что объект реализует необходимый интерфейс
Благодаря полиморфизму код, написанный для интерфейса, будет работать с любыми новыми классами, реализующими этот интерфейс. Но если в коде используются многочисленные конкретные классы, его придется изменять с добавлением новых конкретных классов. Иначе говоря, код перестает быть «закрытым для изменения» — для расширения новыми конкретными типами его придется открывать
т определить аспекты, которые будут изменяться, и отделить их от тех, которые останутся неизменными
Принцип проектирования Стремитесь к слабой связанности взаимодействующих объектов.
На базе слабосвязанных архитектур строятся гибкие ОО-системы, которые хорошо адаптируются к изменениям благодаря минимальным зависимостям между объектами.
- Поведение, унаследованное посредством субклассирования, задается статически на стадии компиляции. Кроме того, оно должно наследоваться всеми субклассами.
- Расширение поведения объекта посредством композиции может осуществляться динамически, наделить объект новыми возможностями — даже теми, которые не были предусмотрены при проектировании суперкласса.
- Динамическая композиция объектов позволяет добавлять новую функциональность посредством написания нового кода (вместо изменения существующего). Так как мы не изменяем готовый код, риск введения ошибок или непредвиденных побочных эффектов значительно снижается
ПОВСЕМЕСТНОЕ применение принципа открытости/закрытости неэффективно и расточительно, оно приводит к созданию сложного, малопонятного кода
Команда и Стратегия похожи по духу, но отличаются масштабом и применением: Команду используют, чтобы превратить любые разнородные действия в объекты. Параметры операции превращаются в поля объекта. Этот объект теперь можно логировать, хранить в истории для отмены, передавать во внешние сервисы и так далее. С другой стороны, Стратегия описывает разные способы произвести одно и то же действие, позволяя взаимозаменять эти способы в каком-то объекте контекста.
DI - Dependency Injection Внедрение зависимостей — это стиль настройки объекта, при котором поля объекта задаются внешней сущностью. Другими словами, объекты настраиваются внешними объектами.