1070 просмотров
От 7 октября 2023

Раскрытие на примерах почти всех паттернов проектирования

1

Что такое шаблон проектирования?

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

2

Группы шаблонов проектирования

Шаблоны проектирования делятся на три группы: 1. Порождающие - описывают создание объекта (instantiation) или группы связанных объектов. 2. Структурные - в основном посвящены компоновке объектов (object composition). То есть тому, как сущности могут друг друга использовать. 3. Поведенченские - связаны с присвоением обязанностей (responsibilities) объектам. От структурных шаблонов они отличаются тем, что не просто описывают структуру, но и очерчивают шаблоны передачи данных, обеспечения взаимодействия.

3

Порождающие шаблоны

Вкратце Порождающие шаблоны описывают создание (instantiate) объекта или группы связанных объектов. Википедия В программной инженерии порождающими называют шаблоны, которые используют механизмы создания объектов, чтобы создавать объекты подходящим для данной ситуации способом. Базовый способ создания может привести к проблемам в архитектуре или к её усложнению. Порождающие шаблоны пытаются решать эти проблемы, управляя способом создания объектов. - Простая фабрика - Фабричный метод - Абстрактная фабрика - Строитель - Прототип - Одиночка

4

Простая фабрика

Аналогия Допустим, вы строите дом и вам нужны двери. Будет бардак, если каждый раз, когда вам требуется дверь, вы станете вооружаться инструментами и делать её на стройплощадке. Вместо этого вы закажете двери на фабрике. Вкратце Простая фабрика просто генерирует экземпляр для клиента без предоставления какой-либо логики экземпляра. Википедия В объектно ориентированном программировании фабрикой называется объект, создающий другие объекты. Формально фабрика — это функция или метод, возвращающая объекты разных прототипов или классов из вызова какого-то метода, который считается новым. Когда использовать? Когда создание объекта подразумевает какую-то логику, а не просто несколько присваиваний, то имеет смысл делегировать задачу выделенной фабрике, а не повторять повсюду один и тот же код. Пример Для начала нам нужен интерфейс двери и его реализация. interface Door { public function getWidth(): float; public function getHeight(): float; } class WoodenDoor implements Door { protected $width; protected $height; public function __construct(float $width, float $height) { $this->width = $width; $this->height = $height; } public function getWidth(): float { return $this->width; } public function getHeight(): float { return $this->height; } } Теперь соорудим фабрику дверей, которая создаёт и возвращает нам двери. class DoorFactory { public static function makeDoor($width, $height): Door { return new WoodenDoor($width, $height); } } Использование: $door = DoorFactory:makeDoor(100, 200); echo 'Width: ' . $door->getWidth(); echo 'Height: ' . $door->getHeight();

5

Фабричный метод

Аналогия Одна кадровичка не в силах провести собеседования со всеми кандидатами на все должности. В зависимости от вакансии она может делегировать разные этапы собеседований разным сотрудникам. Вкратце Это способ делегирования логики создания объектов (instantiation logic) дочерним классам. Википедия В классо-ориентированном программировании (class-based programming) фабричным методом называют порождающий шаблон проектирования, использующий генерирующие методы (factory method) для решения проблемы создания объектов без указания для них конкретных классов. Объекты создаются посредством вызова не конструктора, а генерирующего метода, определённого в интерфейсе и реализованного дочерними классами либо реализованного в базовом классе и, опционально, переопределённого (overridden) производными классами (derived classes). Когда использовать? Этот шаблон полезен для каких-то общих обработок в классе, но требуемые подклассы динамически определяются в ходе выполнения (runtime). То есть когда клиент не знает, какой именно подкласс может ему понадобиться. Пример Сначала создадим интерфейс сотрудника, проводящего собеседование, и некоторые реализации для него. interface Interviewer { public function askQuestions(); } class Developer implements Interviewer { public function askQuestions() { echo 'Asking about design patterns!'; } } class CommunityExecutive implements Interviewer { public function askQuestions() { echo 'Asking about community building'; } } Теперь создадим кадровичку HiringManager. abstract class HiringManager { // Фабричный метод abstract public function makeInterviewer(): Interviewer; public function takeInterview() { $interviewer = $this->makeInterviewer(); $interviewer->askQuestions(); } } Любой дочерний класс может расширять его и предоставлять нужного собеседующего: class DevelopmentManager extends HiringManager { public function makeInterviewer(): Interviewer { return new Developer(); } } class MarketingManager extends HiringManager { public function makeInterviewer(): Interviewer { return new CommunityExecutive(); } } Использование: $devManager = new DevelopmentManager(); $devManager->takeInterview(); // Output: Спрашивает о шаблонах проектирования. $marketingManager = new MarketingManager(); $marketingManager->takeInterview(); // Output: Спрашивает о создании сообщества.

6

Абстрактная фабрика

Аналогия Вернёмся к примеру с дверями из «Простой фабрики». В зависимости от своих потребностей вы можете купить деревянную дверь в одном магазине, стальную — в другом, пластиковую — в третьем. Для монтажа вам понадобятся разные специалисты: деревянной двери нужен плотник, стальной — сварщик, пластиковой — спец по ПВХ-профилям. Вкратце Это фабрика фабрик. То есть фабрика, группирующая индивидуальные, но взаимосвязанные/взаимозависимые фабрики без указания для них конкретных классов. Википедия Шаблон «Абстрактная фабрика» описывает способ инкапсулирования группы индивидуальных фабрик, объединённых некой темой, без указания для них конкретных классов. Когда использовать? Когда у вас есть взаимосвязи с не самой простой логикой создания (creation logic). Пример interface DoorFactory { public function makeDoor(): Door; public function makeFittingExpert(): DoorFittingExpert; } // Фабрика деревянных дверей возвращает плотника и деревянную дверь class WoodenDoorFactory implements DoorFactory { public function makeDoor(): Door { return new WoodenDoor(); } public function makeFittingExpert(): DoorFittingExpert { return new Carpenter(); } } // Фабрика стальных дверей возвращает стальную дверь и сварщика class IronDoorFactory implements DoorFactory { public function makeDoor(): Door { return new IronDoor(); } public function makeFittingExpert(): DoorFittingExpert { return new Welder(); } } Использование: $woodenFactory = new WoodenDoorFactory(); $door = $woodenFactory->makeDoor(); $expert = $woodenFactory->makeFittingExpert(); $door->getDescription(); // Output: Я деревянная дверь $expert->getDescription(); // Output: Я могу устанавливать только деревянные двери // Same for Iron Factory $ironFactory = new IronDoorFactory(); $door = $ironFactory->makeDoor(); $expert = $ironFactory->makeFittingExpert(); $door->getDescription(); // Output: Я стальная дверь $expert->getDescription(); // Output: Я могу устанавливать только стальные двери

7

Строитель

Аналогия Допустим, вы пришли в забегаловку, заказали бургер дня, и вам выдали его без вопросов. Это пример «Простой фабрики». Но иногда логика создания состоит из большего количества шагов. К примеру, при заказе бургера дня есть несколько вариантов хлеба, начинки, соусов, дополнительных ингредиентов. В таких ситуациях помогает шаблон «Строитель». Вкратце Шаблон позволяет создавать разные свойства объекта, избегая загрязнения конструктора (constructor pollution). Это полезно, когда у объекта может быть несколько свойств. Или когда создание объекта состоит из большого количества этапов. Википедия Шаблон «Строитель» предназначен для поиска решения проблемы антипаттерна Telescoping constructor. Поясню, что такое антипаттерн Telescoping constructor. Каждый из нас когда-либо сталкивался с подобным конструктором: public function __construct( $size, $cheese = true, $pepperoni = true, $tomato = false, $lettuce = true ) Как видите, количество параметров может быстро разрастись, и станет трудно разобраться в их структуре. Кроме того, этот список параметров будет расти и дальше, если в будущем вы захотите добавить новые опции. Это и есть антипаттерн Telescoping constructor. Когда использовать? Когда у объекта может быть несколько свойств и когда нужно избежать Telescoping constructor. Ключевое отличие от шаблона «Простая фабрика»: он используется в одноэтапном создании, а «Строитель» — в многоэтапном. Пример Сначала создадим бургер: class Burger { protected $size; protected $cheese = false; protected $pepperoni = false; protected $lettuce = false; protected $tomato = false; public function __construct(BurgerBuilder $builder) { $this->size = $builder->size; $this->cheese = $builder->cheese; $this->pepperoni = $builder->pepperoni; $this->lettuce = $builder->lettuce; $this->tomato = $builder->tomato; } } А затем добавим «строителя»: class BurgerBuilder { public $size; public $cheese = false; public $pepperoni = false; public $lettuce = false; public $tomato = false; public function __construct(int $size) { $this->size = $size; } public function addPepperoni() { $this->pepperoni = true; return $this; } public function addLettuce() { $this->lettuce = true; return $this; } public function addCheese() { $this->cheese = true; return $this; } public function addTomato() { $this->tomato = true; return $this; } public function build(): Burger { return new Burger($this); } } Использование: $burger = (new BurgerBuilder(14)) ->addPepperoni() ->addLettuce() ->addTomato() ->build();

8

Прототип

Аналогия Помните клонированную овечку Долли? Так вот, этот шаблон проектирования как раз посвящён клонированию. Вкратце Объект создаётся посредством клонирования существующего объекта. Википедия Шаблон «Прототип» используется, когда типы создаваемых объектов определяются экземпляром-прототипом, клонированным для создания новых объектов. То есть шаблон позволяет дублировать существующий объект и модифицировать копию в соответствии с потребностями. Без заморочек с созданием объекта с нуля и его настройкой. Когда использовать? Когда необходимый объект аналогичен уже существующему или когда создание с нуля дороже клонирования. Пример В PHP это легко можно сделать с помощью clone: class Sheep { protected $name; protected $category; public function __construct(string $name, string $category = 'Mountain Sheep') { $this->name = $name; $this->category = $category; } public function setName(string $name) { $this->name = $name; } public function getName() { return $this->name; } public function setCategory(string $category) { $this->category = $category; } public function getCategory() { return $this->category; } } Затем можно клонировать так: $original = new Sheep('Jolly'); echo $original->getName(); // Джолли echo $original->getCategory(); // Горная овечка // Клонируйте и модифицируйте, что нужно $cloned = clone $original; $cloned->setName('Dolly'); echo $cloned->getName(); // Долли echo $cloned->getCategory(); // Горная овечка Также для модификации процедуры клонирования можно обратиться к магическому методу __clone.

Логотип ДевстанцииАвторизуйтесь, чтобы просматривать следующий контент
10

Одиночка

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
11

Структурные шаблоны

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
12

Адаптер

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
13

Мост.

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
14

Компоновщик

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
15

Декоратор

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
16

Фасад

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
17

Приспособленец

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
18

Заместитель

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
19

Поведенченские шаблоны

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
20

Цепочка ответственности

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
21

Команда

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
22

Итератор

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
23

Посредник

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
24

Хранитель

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
25

Наблюдатель

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
26

Посетитель

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
27

Стратегия

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
28

Состояние

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
29

Шаблонный метод

Логотип ДевстанцииАвторизуйтесь, чтобы получить доступ
Хотите стать частью сообщества Девстанции?
Вступайте в наш чат в Telegram

Также в этой категории

Вопросник
  11 вопросов

Вопросы про HTTP, SSL, WebSocket и прочее

Вопросы для собеседования бэкенд-разработчика

1149 просмотров
От 12 октября 2023
Вопросник
  13 вопросов

Общие принципы и понятия ООП

Вопросы для собеседования по теме ООП

908 просмотров
От 7 октября 2023
Вопросник
  15 вопросов

Вопросы с собеседований по DDD

Ответы на вопросы про Domain-Driven Design

1104 просмотра
От 4 июня
Вопросник
  12 вопросов

Операционные системы: базовые понятия

Потоки, процессы, конкурентность и прочие понятия из мира ОС

862 просмотра
От 27 января

Вам может быть интересно

Вопросник
  7 вопросов

Коллекция полезных команд для Docker

Большая шпаргалка по всем командам Docker

1021 просмотр
От 12 октября 2023
Вопросник
  10 вопросов

Всё о репликации баз данных

Описание понятий и процессов репликации БД

1097 просмотров
От 8 октября 2023
Вопросник
  60 вопросов

Топ 60 вопросов про базы данных и SQL

Ответы на вопросы с собеседований по БД и SQL

1713 просмотров
От 4 июня
Вопросник
  11 вопросов

Теория шардинга баз данных

О распределении данных между серверами

982 просмотра
От 10 октября 2023

Топ тредов

Gravatar for 1623bbush
bbush
: Задача в JavaScript "Числовая спираль"

Последнее сообщение:
Gravatar for 1773kartan
Kartan
: В матрице размером 4x3 не может быть числа 13, максимальное количество цифр - 12. В тесте ошибка
2 сообщения
38 просмотров

Gravatar for 1847arsen
Arsen
: Задача в Python под названием "Кратчайший путь в матрице"

Последнее сообщение:
Gravatar for 1847arsen
Arsen
: Ошибка на 3 тесте # Ожидаемый результат: 2 а должен быть 1
1 сообщение
67 просмотров

Gravatar for 1233freddypopa
freddypopa
: Добавить чекбокс, который отвечает за показ ранее тронутых задач (черновик)

Последнее сообщение:
: Отличная идея! Возьмём её на заметку!
1 сообщение
166 просмотров

Все категории