├── LICENSE ├── README.md └── README_en.md /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Kamran Ahmed 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Design Patterns For Humans](https://cloud.githubusercontent.com/assets/11269635/23065273/1b7e5938-f515-11e6-8dd3-d0d58de6bb9a.png) 2 | 3 | # Шаблоны (паттерны) проектирования для людей 4 | 5 | *** 6 |

7 | 🎉 Ультра-простое объяснение шаблонов проектирования! 🎉 8 |

9 |

10 | Тема, которая может легко смутить любого. Я, на максимально простых примерах, стараюсь объяснить их и оставить след в вашей (и, возможно, своей) голове. 11 |

12 | 13 | *** 14 | 15 | 🚀 Вступление 16 | ================= 17 | 18 | Шаблоны проектирования являются решениями некоторых часто возникающих ситуаций; **руководством как решать определенные задачи**. Они не классы, пакеты или библиотеки, которые вы могли бы подключить к вашему приложению и ожидать что случится чудо. Они, скорее, путеводители как решить определенную проблему в определенном контексте. 19 | 20 | > Шаблоны проектирования - решения повторяющихся проблем; руководства как решить определенную проблему 21 | 22 | [Википедия](https://ru.wikipedia.org/wiki/%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F#.D0.9E.D1.81.D0.BD.D0.BE.D0.B2.D0.BD.D1.8B.D0.B5) опысывает их как: 23 | 24 | > В разработке программного обеспечения — повторяемая архитектурная конструкция, представляющая собой решение проблемы проектирования в рамках некоторого часто возникающего контекста. Обычно шаблон не является законченным образцом, который может быть прямо преобразован в код; это лишь пример решения задачи, который можно использовать в различных ситуациях. *(здесь и далее цитаты из русскоязычной Википедии, если не указано обратное - прим. переводчика)* 25 | 26 | 27 | ⚠️ Будьте осторожны 28 | ----------------- 29 | - Шаблоны проектирования - не волшебная таблетка от всех проблем. 30 | - Не злоупотребляйте ими, это может привести к неприятностям. Помните, что шаблоны проектирования предназначены для **решения**, а не **добавления** проблем, так что не переусердствуйте. 31 | - Используемые в правильном месте и правильным образом, они подтверждают свою полезность. В противном же случае могут привести к ужасному нагромождению кода. 32 | 33 | > Обратите также внимание, что примеры кода ниже будут на PHP-7 (Javascript - прим. переводчика), что не должно вас останавливать потому, что концепция все-равно одна и та же. Плюс, на подходе **поддержка других языков** 34 | 35 | Типы Шаблонов Проектирования 36 | ----------------- 37 | 38 | * [Порождающие шаблоны](#Порождающие-Шаблоны-Проектирования) 39 | * [Структурные шаблоны (англ. Structural patterns)](#structural-design-patterns) 40 | * [Поведенческие шаблоны (англ. behavioral patterns)](#behavioral-design-patterns) 41 | 42 | Порождающие Шаблоны Проектирования 43 | ========================== 44 | 45 | Простыми словами: 46 | > Порождающие шаблоны (англ. Creational patterns) сфокусированы на процессе инстанцирования объектов или групп связанных объектов 47 | 48 | [Википедия](https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D1%80%D0%BE%D0%B6%D0%B4%D0%B0%D1%8E%D1%89%D0%B8%D0%B5_%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%8B_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F): 49 | > Порождающие шаблоны - шаблоны проектирования, которые абстрагируют процесс инстанцирования. Они позволяют сделать систему независимой от способа создания, композиции и представления объектов. Шаблон, порождающий классы, использует наследование, чтобы изменять наследуемый класс, а шаблон, порождающий объекты, делегирует инстанцирование другому объекту. 50 | 51 | * [Простая фабрика](#-Простая-фабрика-англ-simple-factory) 52 | * [Фабричный метод](#-Фабричный-метод-англ-factory-method) 53 | * [Абстрактная фабрика](#-Абстрактная-фабрика-англ-abstract-factory) 54 | * [Строитель](#-Строитель-англ-builder) 55 | * [Прототип](#-Прототип-англ-prototype) 56 | * [Одиночка](#-Одиночка-англ-singleton) 57 | 58 | 🏠 Простая фабрика _(англ. simple factory)_ 59 | -------------- 60 | Пример из реального мира 61 | > Представьте, вы стоите дом и вам нужны двери. Это было бы не оправданно, если бы каждый раз, когда вам требуется дверь, вы бы надевали костюм плотника и начинали делать дверь самостоятельно. Вместо этого, дверь для вас могут сделать на фабрике. 62 | 63 | Простыми словами 64 | > Простая фабрика просто создает экземпляр для клиента не предоставляя клиенту какой либо логики создания. 65 | 66 | [Википедия](https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)) 67 | > В объектно-ориентированном программировании (ООП), фабрика - это объект, создающий другие объекты. Формально фабрика это функция или метод, вызов которой возвращает объекты различных классов или прототипов, которые можно считать "новыми". 68 | 69 | **Пример кода** 70 | 71 | Прежде всего у нас есть интерфейс door и его имплементация 72 | ```php 73 | interface Door 74 | { 75 | public function getWidth(): float; 76 | public function getHeight(): float; 77 | } 78 | 79 | class WoodenDoor implements Door 80 | { 81 | protected $width; 82 | protected $height; 83 | 84 | public function __construct(float $width, float $height) 85 | { 86 | $this->width = $width; 87 | $this->height = $height; 88 | } 89 | 90 | public function getWidth(): float 91 | { 92 | return $this->width; 93 | } 94 | 95 | public function getHeight(): float 96 | { 97 | return $this->height; 98 | } 99 | } 100 | ``` 101 | Затем фабрика DoorFactory создает двери и возвращает их. 102 | ```php 103 | class DoorFactory 104 | { 105 | public static function makeDoor($width, $height): Door 106 | { 107 | return new WoodenDoor($width, $height); 108 | } 109 | } 110 | ``` 111 | И затем, мы это можем использовать так 112 | ```php 113 | $door = DoorFactory::makeDoor(100, 200); 114 | echo 'Width: ' . $door->getWidth(); 115 | echo 'Height: ' . $door->getHeight(); 116 | ``` 117 | 118 | **Когда использовать?** 119 | 120 | Если создание объекта не ограничевается парой присвоений и требует вовлечения определенной логики, имеет смысл вынести ее в отдельную фабрику вместо постоянного повторения одного и того же кода. 121 | 122 | 🏭 Фабричный метод _(англ. factory method)_ 123 | -------------- 124 | 125 | Пример из реального мира 126 | > Предположим, есть менеджер по персоналу. Ей не по силам в одиночку проводить интервью на все позиции. В зависимости от требований к должности, ей нужно определить различных специалистов и передать им полномочия по проведению собеседования. 127 | 128 | Простыми словами 129 | > Обеспечивает возможность передачи логики создания в дочерние классы. 130 | 131 | [Википедия](https://ru.wikipedia.org/wiki/%D0%A4%D0%B0%D0%B1%D1%80%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)) 132 | > Фабричный метод (англ. Factory Method также известен как Виртуальный конструктор (англ. Virtual Constructor)) — порождающий шаблон проектирования, предоставляющий подклассам интерфейс для создания экземпляров некоторого класса. В момент создания наследники могут определить, какой класс создавать. Иными словами, Фабрика делегирует создание объектов наследникам родительского класса. Это позволяет использовать в коде программы не специфические классы, а манипулировать абстрактными объектами на более высоком уровне. 133 | 134 | **Пример кода** 135 | 136 | Возьмем пример нашего менеджера по персоналу. Прежде всего создадим интерфейс Interviewer и несколько его реализаций. 137 | 138 | ```php 139 | interface Interviewer 140 | { 141 | public function askQuestions(); 142 | } 143 | 144 | class Developer implements Interviewer 145 | { 146 | public function askQuestions() 147 | { 148 | echo 'Asking about design patterns!'; 149 | } 150 | } 151 | 152 | class CommunityExecutive implements Interviewer 153 | { 154 | public function askQuestions() 155 | { 156 | echo 'Asking about community building'; 157 | } 158 | } 159 | ``` 160 | 161 | Теперь давайте создадим `HiringManager` 162 | 163 | ```php 164 | abstract class HiringManager 165 | { 166 | 167 | // Factory method 168 | abstract public function makeInterviewer(): Interviewer; 169 | 170 | public function takeInterview() 171 | { 172 | $interviewer = $this->makeInterviewer(); 173 | $interviewer->askQuestions(); 174 | } 175 | } 176 | 177 | ``` 178 | 179 | Теперь любой потомок может наследовать его и предоставить требуемый Interviewer 180 | 181 | ```php 182 | class DevelopmentManager extends HiringManager 183 | { 184 | public function makeInterviewer(): Interviewer 185 | { 186 | return new Developer(); 187 | } 188 | } 189 | 190 | class MarketingManager extends HiringManager 191 | { 192 | public function makeInterviewer(): Interviewer 193 | { 194 | return new CommunityExecutive(); 195 | } 196 | } 197 | ``` 198 | затем это может быть использованно следующим образом 199 | 200 | ```php 201 | $devManager = new DevelopmentManager(); 202 | $devManager->takeInterview(); // Output: Asking about design patterns 203 | 204 | $marketingManager = new MarketingManager(); 205 | $marketingManager->takeInterview(); // Output: Asking about community building. 206 | ``` 207 | 208 | **Когда использовать?** 209 | 210 | Полезно когда в классе присутствуют несколько общих процессов, но требуемый подкласс определяется динамично во время исполнения. Или другими словами, когда клиент не знает какой конкретно подкласс может потребоваться. 211 | 212 | 🔨 Абстрактная фабрика _(англ. abstract factory)_ 213 | ---------------- 214 | 215 | Пример из реального мира 216 | > Расширим пример с дверьми из простой фабрики. В зависимости от ваших нужд вы можете захотеть деревянную дверь из магазина деревянных дверей, железную дверь из магазина железных дверей или пластиковую дверь из соответствующего магазина. Плюс вам может понадобиться установщик с нужной специальностью, например, плотник для деревянной двери, жестянщик для металической и так далее. Как вы можете видеть, теперь существует зависимость между дверми: деревянная требует плотника, металлическая - жестянщика и т.д. 217 | 218 | Простыми словами 219 | > Фабрика фабрик; фабика, которая группирует индивидуальные, но связанные/зависимые фабрики вместе без указания их конкретных классов. 220 | 221 | [Википедия](https://ru.wikipedia.org/wiki/%D0%90%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%82%D0%BD%D0%B0%D1%8F_%D1%84%D0%B0%D0%B1%D1%80%D0%B8%D0%BA%D0%B0_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)) 222 | > Абстрактная фабрика (англ. Abstract factory) — порождающий шаблон проектирования, предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна и кнопки). Затем пишутся классы, реализующие этот интерфейс. 223 | 224 | **Пример кода** 225 | 226 | Реализуем описанный пример с дверьми. Прежде всего у нас будет интерфейс `Door` и несколько его имплементаций. 227 | 228 | ```php 229 | interface Door 230 | { 231 | public function getDescription(); 232 | } 233 | 234 | class WoodenDoor implements Door 235 | { 236 | public function getDescription() 237 | { 238 | echo 'I am a wooden door'; 239 | } 240 | } 241 | 242 | class IronDoor implements Door 243 | { 244 | public function getDescription() 245 | { 246 | echo 'I am an iron door'; 247 | } 248 | } 249 | ``` 250 | Затем у нас будут несколько соответствующих экспертов для каждого вида двери 251 | 252 | ```php 253 | interface DoorFittingExpert 254 | { 255 | public function getDescription(); 256 | } 257 | 258 | class Welder implements DoorFittingExpert 259 | { 260 | public function getDescription() 261 | { 262 | echo 'I can only fit iron doors'; 263 | } 264 | } 265 | 266 | class Carpenter implements DoorFittingExpert 267 | { 268 | public function getDescription() 269 | { 270 | echo 'I can only fit wooden doors'; 271 | } 272 | } 273 | ``` 274 | 275 | Теперь создадим абстрактную фабрику, которая бы позволяла создавать семейство взаимосвязанных объектов, например, фабрика деревянных дверей создает деревянную двурь и эксперта по деревянным дверям, а фабрика железных дверей должна создавать железные двери и экспертов по ним. 276 | ```php 277 | interface DoorFactory 278 | { 279 | public function makeDoor(): Door; 280 | public function makeFittingExpert(): DoorFittingExpert; 281 | } 282 | 283 | // Wooden factory to return carpenter and wooden door 284 | class WoodenDoorFactory implements DoorFactory 285 | { 286 | public function makeDoor(): Door 287 | { 288 | return new WoodenDoor(); 289 | } 290 | 291 | public function makeFittingExpert(): DoorFittingExpert 292 | { 293 | return new Carpenter(); 294 | } 295 | } 296 | 297 | // Iron door factory to get iron door and the relevant fitting expert 298 | class IronDoorFactory implements DoorFactory 299 | { 300 | public function makeDoor(): Door 301 | { 302 | return new IronDoor(); 303 | } 304 | 305 | public function makeFittingExpert(): DoorFittingExpert 306 | { 307 | return new Welder(); 308 | } 309 | } 310 | ``` 311 | затем это может быть использованно следующим образом 312 | ```php 313 | $woodenFactory = new WoodenDoorFactory(); 314 | 315 | $door = $woodenFactory->makeDoor(); 316 | $expert = $woodenFactory->makeFittingExpert(); 317 | 318 | $door->getDescription(); // Output: I am a wooden door 319 | $expert->getDescription(); // Output: I can only fit wooden doors 320 | 321 | // Same for Iron Factory 322 | $ironFactory = new IronDoorFactory(); 323 | 324 | $door = $ironFactory->makeDoor(); 325 | $expert = $ironFactory->makeFittingExpert(); 326 | 327 | $door->getDescription(); // Output: I am an iron door 328 | $expert->getDescription(); // Output: I can only fit iron doors 329 | ``` 330 | 331 | Как вы можете видеть, фабрика деревянных дверей инкапсулирует `carpenter` и `wooden door`, в то время как фабрика железных дверей инкапсулирует `iron door` и `welder`. И таким образом, это дает нам уверенность, что для каждой созданной двери мы не перепутаем соответствующего эксперта. 332 | 333 | **Когда использовать?** 334 | 335 | Когда существуют взаимодействующие зависимости с не-совсем-простой логикой создания. 336 | 337 | 👷 Строитель _(англ. builder)_ 338 | -------------------------------------------- 339 | Пример из реального мира 340 | > Imagine you are at Hardee's and you order a specific deal, lets say, "Big Hardee" and they hand it over to you without *any questions*; this is the example of simple factory. But there are cases when the creation logic might involve more steps. For example you want a customized Subway deal, you have several options in how your burger is made e.g what bread do you want? what types of sauces would you like? What cheese would you want? etc. In such cases builder pattern comes to the rescue. 341 | 342 | Простыми словами 343 | > Allows you to create different flavors of an object while avoiding constructor pollution. Useful when there could be several flavors of an object. Or when there are a lot of steps involved in creation of an object. 344 | 345 | [Википедия](https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)) 346 | > Строитель (англ. Builder) — порождающий шаблон проектирования предоставляет способ создания составного объекта. 347 | 348 | Having said that let me add a bit about what telescoping constructor anti-pattern is. At one point or the other we have all seen a constructor like below: 349 | 350 | ```php 351 | public function __construct($size, $cheese = true, $pepperoni = true, $tomato = false, $lettuce = true) 352 | { 353 | } 354 | ``` 355 | 356 | As you can see; the number of constructor parameters can quickly get out of hand and it might become difficult to understand the arrangement of parameters. Plus this parameter list could keep on growing if you would want to add more options in future. This is called telescoping constructor anti-pattern. 357 | 358 | **Пример кода** 359 | 360 | The sane alternative is to use the builder pattern. First of all we have our burger that we want to make 361 | 362 | ```php 363 | class Burger 364 | { 365 | protected $size; 366 | 367 | protected $cheese = false; 368 | protected $pepperoni = false; 369 | protected $lettuce = false; 370 | protected $tomato = false; 371 | 372 | public function __construct(BurgerBuilder $builder) 373 | { 374 | $this->size = $builder->size; 375 | $this->cheese = $builder->cheese; 376 | $this->pepperoni = $builder->pepperoni; 377 | $this->lettuce = $builder->lettuce; 378 | $this->tomato = $builder->tomato; 379 | } 380 | } 381 | ``` 382 | 383 | And then we have the builder 384 | 385 | ```php 386 | class BurgerBuilder 387 | { 388 | public $size; 389 | 390 | public $cheese = false; 391 | public $pepperoni = false; 392 | public $lettuce = false; 393 | public $tomato = false; 394 | 395 | public function __construct(int $size) 396 | { 397 | $this->size = $size; 398 | } 399 | 400 | public function addPepperoni() 401 | { 402 | $this->pepperoni = true; 403 | return $this; 404 | } 405 | 406 | public function addLettuce() 407 | { 408 | $this->lettuce = true; 409 | return $this; 410 | } 411 | 412 | public function addCheese() 413 | { 414 | $this->cheese = true; 415 | return $this; 416 | } 417 | 418 | public function addTomato() 419 | { 420 | $this->tomato = true; 421 | return $this; 422 | } 423 | 424 | public function build(): Burger 425 | { 426 | return new Burger($this); 427 | } 428 | } 429 | ``` 430 | И затем, мы это можем использовать так: 431 | 432 | ```php 433 | $burger = (new BurgerBuilder(14)) 434 | ->addPepperoni() 435 | ->addLettuce() 436 | ->addTomato() 437 | ->build(); 438 | ``` 439 | 440 | **Когда использовать?** 441 | 442 | When there could be several flavors of an object and to avoid the constructor telescoping. The key difference from the factory pattern is that; factory pattern is to be used when the creation is a one step process while builder pattern is to be used when the creation is a multi step process. 443 | 444 | 🐑 Прототип _(англ. prototype)_ 445 | ------------ 446 | Пример из реального мира 447 | > Remember dolly? The sheep that was cloned! Lets not get into the details but the key point here is that it is all about cloning 448 | 449 | Простыми словами 450 | > Create object based on an existing object through cloning. 451 | 452 | [Википедия](https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%82%D0%BE%D1%82%D0%B8%D0%BF_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)) 453 | > Задаёт виды создаваемых объектов с помощью экземпляра-прототипа и создаёт новые объекты путём копирования этого прототипа. Он позволяет уйти от реализации и позволяет следовать принципу «программирование через интерфейсы». В качестве возвращающего типа указывается интерфейс/абстрактный класс на вершине иерархии, а классы-наследники могут подставить туда наследника, реализующего этот тип. 454 | Проще говоря, это паттерн создания объекта через клонирование другого объекта вместо создания через конструктор. 455 | 456 | In short, it allows you to create a copy of an existing object and modify it to your needs, instead of going through the trouble of creating an object from scratch and setting it up. 457 | 458 | **Пример кода** 459 | 460 | In PHP, it can be easily done using `clone` 461 | 462 | ```php 463 | class Sheep 464 | { 465 | protected $name; 466 | protected $category; 467 | 468 | public function __construct(string $name, string $category = 'Mountain Sheep') 469 | { 470 | $this->name = $name; 471 | $this->category = $category; 472 | } 473 | 474 | public function setName(string $name) 475 | { 476 | $this->name = $name; 477 | } 478 | 479 | public function getName() 480 | { 481 | return $this->name; 482 | } 483 | 484 | public function setCategory(string $category) 485 | { 486 | $this->category = $category; 487 | } 488 | 489 | public function getCategory() 490 | { 491 | return $this->category; 492 | } 493 | } 494 | ``` 495 | Then it can be cloned like below 496 | ```php 497 | $original = new Sheep('Jolly'); 498 | echo $original->getName(); // Jolly 499 | echo $original->getCategory(); // Mountain Sheep 500 | 501 | // Clone and modify what is required 502 | $cloned = clone $original; 503 | $cloned->setName('Dolly'); 504 | echo $cloned->getName(); // Dolly 505 | echo $cloned->getCategory(); // Mountain sheep 506 | ``` 507 | 508 | Also you could use the magic method `__clone` to modify the cloning behavior. 509 | 510 | **Когда использовать?** 511 | 512 | When an object is required that is similar to existing object or when the creation would be expensive as compared to cloning. 513 | 514 | 💍 Одиночка _(англ. singleton)_ 515 | ------------ 516 | Пример из реального мира 517 | > There can only be one president of a country at a time. The same president has to be brought to action, whenever duty calls. President here is singleton. 518 | 519 | Простыми словами 520 | > Ensures that only one object of a particular class is ever created. 521 | 522 | [Википедия](https://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BA%D0%B0_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)) 523 | > Одиночка (англ. Singleton) — порождающий шаблон проектирования, гарантирующий, что в однопроцессном приложении будет единственный экземпляр некоторого класса, и предоставляющий глобальную точку доступа к этому экземпляру.. 524 | 525 | Singleton pattern is actually considered an anti-pattern and overuse of it should be avoided. It is not necessarily bad and could have some valid use-cases but should be used with caution because it introduces a global state in your application and change to it in one place could affect in the other areas and it could become pretty difficult to debug. The other bad thing about them is it makes your code tightly coupled plus it mocking the singleton could be difficult. 526 | 527 | **Пример кода** 528 | 529 | To create a singleton, make the constructor private, disable cloning, disable extension and create a static variable to house the instance 530 | ```php 531 | final class President 532 | { 533 | private static $instance; 534 | 535 | private function __construct() 536 | { 537 | // Hide the constructor 538 | } 539 | 540 | public static function getInstance(): President 541 | { 542 | if (!self::$instance) { 543 | self::$instance = new self(); 544 | } 545 | 546 | return self::$instance; 547 | } 548 | 549 | private function __clone() 550 | { 551 | // Disable cloning 552 | } 553 | 554 | private function __wakeup() 555 | { 556 | // Disable unserialize 557 | } 558 | } 559 | ``` 560 | Then in order to use 561 | ```php 562 | $president1 = President::getInstance(); 563 | $president2 = President::getInstance(); 564 | 565 | var_dump($president1 === $president2); // true 566 | ``` 567 | 568 | Structural Design Patterns 569 | ========================== 570 | In plain words 571 | > Structural patterns are mostly concerned with object composition or in other words how the entities can use each other. Or yet another explanation would be, they help in answering "How to build a software component?" 572 | 573 | Wikipedia says 574 | > In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities. 575 | 576 | * [Adapter](#-adapter) 577 | * [Bridge](#-bridge) 578 | * [Composite](#-composite) 579 | * [Decorator](#-decorator) 580 | * [Facade](#-facade) 581 | * [Flyweight](#-flyweight) 582 | * [Proxy](#-proxy) 583 | 584 | 🔌 Adapter 585 | ------- 586 | Real world example 587 | > Consider that you have some pictures in your memory card and you need to transfer them to your computer. In order to transfer them you need some kind of adapter that is compatible with your computer ports so that you can attach memory card to your computer. In this case card reader is an adapter. 588 | > Another example would be the famous power adapter; a three legged plug can't be connected to a two pronged outlet, it needs to use a power adapter that makes it compatible with the two pronged outlet. 589 | > Yet another example would be a translator translating words spoken by one person to another 590 | 591 | In plain words 592 | > Adapter pattern lets you wrap an otherwise incompatible object in an adapter to make it compatible with another class. 593 | 594 | Wikipedia says 595 | > In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code. 596 | 597 | **Programmatic Example** 598 | 599 | Consider a game where there is a hunter and he hunts lions. 600 | 601 | First we have an interface `Lion` that all types of lions have to implement 602 | 603 | ```php 604 | interface Lion 605 | { 606 | public function roar(); 607 | } 608 | 609 | class AfricanLion implements Lion 610 | { 611 | public function roar() 612 | { 613 | } 614 | } 615 | 616 | class AsianLion implements Lion 617 | { 618 | public function roar() 619 | { 620 | } 621 | } 622 | ``` 623 | And hunter expects any implementation of `Lion` interface to hunt. 624 | ```php 625 | class Hunter 626 | { 627 | public function hunt(Lion $lion) 628 | { 629 | } 630 | } 631 | ``` 632 | 633 | Now let's say we have to add a `WildDog` in our game so that hunter can hunt that also. But we can't do that directly because dog has a different interface. To make it compatible for our hunter, we will have to create an adapter that is compatible 634 | 635 | ```php 636 | // This needs to be added to the game 637 | class WildDog 638 | { 639 | public function bark() 640 | { 641 | } 642 | } 643 | 644 | // Adapter around wild dog to make it compatible with our game 645 | class WildDogAdapter implements Lion 646 | { 647 | protected $dog; 648 | 649 | public function __construct(WildDog $dog) 650 | { 651 | $this->dog = $dog; 652 | } 653 | 654 | public function roar() 655 | { 656 | $this->dog->bark(); 657 | } 658 | } 659 | ``` 660 | And now the `WildDog` can be used in our game using `WildDogAdapter`. 661 | 662 | ```php 663 | $wildDog = new WildDog(); 664 | $wildDogAdapter = new WildDogAdapter($wildDog); 665 | 666 | $hunter = new Hunter(); 667 | $hunter->hunt($wildDogAdapter); 668 | ``` 669 | 670 | 🚡 Bridge 671 | ------ 672 | Real world example 673 | > Consider you have a website with different pages and you are supposed to allow the user to change the theme. What would you do? Create multiple copies of each of the pages for each of the themes or would you just create separate theme and load them based on the user's preferences? Bridge pattern allows you to do the second i.e. 674 | 675 | ![With and without the bridge pattern](https://cloud.githubusercontent.com/assets/11269635/23065293/33b7aea0-f515-11e6-983f-98823c9845ee.png) 676 | 677 | In Plain Words 678 | > Bridge pattern is about preferring composition over inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy. 679 | 680 | Wikipedia says 681 | > The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently" 682 | 683 | **Programmatic Example** 684 | 685 | Translating our WebPage example from above. Here we have the `WebPage` hierarchy 686 | 687 | ```php 688 | interface WebPage 689 | { 690 | public function __construct(Theme $theme); 691 | public function getContent(); 692 | } 693 | 694 | class About implements WebPage 695 | { 696 | protected $theme; 697 | 698 | public function __construct(Theme $theme) 699 | { 700 | $this->theme = $theme; 701 | } 702 | 703 | public function getContent() 704 | { 705 | return "About page in " . $this->theme->getColor(); 706 | } 707 | } 708 | 709 | class Careers implements WebPage 710 | { 711 | protected $theme; 712 | 713 | public function __construct(Theme $theme) 714 | { 715 | $this->theme = $theme; 716 | } 717 | 718 | public function getContent() 719 | { 720 | return "Careers page in " . $this->theme->getColor(); 721 | } 722 | } 723 | ``` 724 | And the separate theme hierarchy 725 | ```php 726 | 727 | interface Theme 728 | { 729 | public function getColor(); 730 | } 731 | 732 | class DarkTheme implements Theme 733 | { 734 | public function getColor() 735 | { 736 | return 'Dark Black'; 737 | } 738 | } 739 | class LightTheme implements Theme 740 | { 741 | public function getColor() 742 | { 743 | return 'Off white'; 744 | } 745 | } 746 | class AquaTheme implements Theme 747 | { 748 | public function getColor() 749 | { 750 | return 'Light blue'; 751 | } 752 | } 753 | ``` 754 | And both the hierarchies 755 | ```php 756 | $darkTheme = new DarkTheme(); 757 | 758 | $about = new About($darkTheme); 759 | $careers = new Careers($darkTheme); 760 | 761 | echo $about->getContent(); // "About page in Dark Black"; 762 | echo $careers->getContent(); // "Careers page in Dark Black"; 763 | ``` 764 | 765 | 🌿 Composite 766 | ----------------- 767 | 768 | Real world example 769 | > Every organization is composed of employees. Each of the employees has the same features i.e. has a salary, has some responsibilities, may or may not report to someone, may or may not have some subordinates etc. 770 | 771 | In plain words 772 | > Composite pattern lets clients treat the individual objects in a uniform manner. 773 | 774 | Wikipedia says 775 | > In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly. 776 | 777 | **Programmatic Example** 778 | 779 | Taking our employees example from above. Here we have different employee types 780 | 781 | ```php 782 | interface Employee 783 | { 784 | public function __construct(string $name, float $salary); 785 | public function getName(): string; 786 | public function setSalary(float $salary); 787 | public function getSalary(): float; 788 | public function getRoles(): array; 789 | } 790 | 791 | class Developer implements Employee 792 | { 793 | protected $salary; 794 | protected $name; 795 | 796 | public function __construct(string $name, float $salary) 797 | { 798 | $this->name = $name; 799 | $this->salary = $salary; 800 | } 801 | 802 | public function getName(): string 803 | { 804 | return $this->name; 805 | } 806 | 807 | public function setSalary(float $salary) 808 | { 809 | $this->salary = $salary; 810 | } 811 | 812 | public function getSalary(): float 813 | { 814 | return $this->salary; 815 | } 816 | 817 | public function getRoles(): array 818 | { 819 | return $this->roles; 820 | } 821 | } 822 | 823 | class Designer implements Employee 824 | { 825 | protected $salary; 826 | protected $name; 827 | 828 | public function __construct(string $name, float $salary) 829 | { 830 | $this->name = $name; 831 | $this->salary = $salary; 832 | } 833 | 834 | public function getName(): string 835 | { 836 | return $this->name; 837 | } 838 | 839 | public function setSalary(float $salary) 840 | { 841 | $this->salary = $salary; 842 | } 843 | 844 | public function getSalary(): float 845 | { 846 | return $this->salary; 847 | } 848 | 849 | public function getRoles(): array 850 | { 851 | return $this->roles; 852 | } 853 | } 854 | ``` 855 | 856 | Then we have an organization which consists of several different types of employees 857 | 858 | ```php 859 | class Organization 860 | { 861 | protected $employees; 862 | 863 | public function addEmployee(Employee $employee) 864 | { 865 | $this->employees[] = $employee; 866 | } 867 | 868 | public function getNetSalaries(): float 869 | { 870 | $netSalary = 0; 871 | 872 | foreach ($this->employees as $employee) { 873 | $netSalary += $employee->getSalary(); 874 | } 875 | 876 | return $netSalary; 877 | } 878 | } 879 | ``` 880 | 881 | And then it can be used as 882 | 883 | ```php 884 | // Prepare the employees 885 | $john = new Developer('John Doe', 12000); 886 | $jane = new Designer('Jane', 10000); 887 | 888 | // Add them to organization 889 | $organization = new Organization(); 890 | $organization->addEmployee($john); 891 | $organization->addEmployee($jane); 892 | 893 | echo "Net salaries: " . $organization->getNetSalaries(); // Net Salaries: 22000 894 | ``` 895 | 896 | ☕ Decorator 897 | ------------- 898 | 899 | Real world example 900 | 901 | > Imagine you run a car service shop offering multiple services. Now how do you calculate the bill to be charged? You pick one service and dynamically keep adding to it the prices for the provided services till you get the final cost. Here each type of service is a decorator. 902 | 903 | In plain words 904 | > Decorator pattern lets you dynamically change the behavior of an object at run time by wrapping them in an object of a decorator class. 905 | 906 | Wikipedia says 907 | > In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern. 908 | 909 | **Programmatic Example** 910 | 911 | Lets take coffee for example. First of all we have a simple coffee implementing the coffee interface 912 | 913 | ```php 914 | interface Coffee 915 | { 916 | public function getCost(); 917 | public function getDescription(); 918 | } 919 | 920 | class SimpleCoffee implements Coffee 921 | { 922 | public function getCost() 923 | { 924 | return 10; 925 | } 926 | 927 | public function getDescription() 928 | { 929 | return 'Simple coffee'; 930 | } 931 | } 932 | ``` 933 | We want to make the code extensible to allow options to modify it if required. Lets make some add-ons (decorators) 934 | ```php 935 | class MilkCoffee implements Coffee 936 | { 937 | protected $coffee; 938 | 939 | public function __construct(Coffee $coffee) 940 | { 941 | $this->coffee = $coffee; 942 | } 943 | 944 | public function getCost() 945 | { 946 | return $this->coffee->getCost() + 2; 947 | } 948 | 949 | public function getDescription() 950 | { 951 | return $this->coffee->getDescription() . ', milk'; 952 | } 953 | } 954 | 955 | class WhipCoffee implements Coffee 956 | { 957 | protected $coffee; 958 | 959 | public function __construct(Coffee $coffee) 960 | { 961 | $this->coffee = $coffee; 962 | } 963 | 964 | public function getCost() 965 | { 966 | return $this->coffee->getCost() + 5; 967 | } 968 | 969 | public function getDescription() 970 | { 971 | return $this->coffee->getDescription() . ', whip'; 972 | } 973 | } 974 | 975 | class VanillaCoffee implements Coffee 976 | { 977 | protected $coffee; 978 | 979 | public function __construct(Coffee $coffee) 980 | { 981 | $this->coffee = $coffee; 982 | } 983 | 984 | public function getCost() 985 | { 986 | return $this->coffee->getCost() + 3; 987 | } 988 | 989 | public function getDescription() 990 | { 991 | return $this->coffee->getDescription() . ', vanilla'; 992 | } 993 | } 994 | ``` 995 | 996 | Lets make a coffee now 997 | 998 | ```php 999 | $someCoffee = new SimpleCoffee(); 1000 | echo $someCoffee->getCost(); // 10 1001 | echo $someCoffee->getDescription(); // Simple Coffee 1002 | 1003 | $someCoffee = new MilkCoffee($someCoffee); 1004 | echo $someCoffee->getCost(); // 12 1005 | echo $someCoffee->getDescription(); // Simple Coffee, milk 1006 | 1007 | $someCoffee = new WhipCoffee($someCoffee); 1008 | echo $someCoffee->getCost(); // 17 1009 | echo $someCoffee->getDescription(); // Simple Coffee, milk, whip 1010 | 1011 | $someCoffee = new VanillaCoffee($someCoffee); 1012 | echo $someCoffee->getCost(); // 20 1013 | echo $someCoffee->getDescription(); // Simple Coffee, milk, whip, vanilla 1014 | ``` 1015 | 1016 | 📦 Facade 1017 | ---------------- 1018 | 1019 | Real world example 1020 | > How do you turn on the computer? "Hit the power button" you say! That is what you believe because you are using a simple interface that computer provides on the outside, internally it has to do a lot of stuff to make it happen. This simple interface to the complex subsystem is a facade. 1021 | 1022 | In plain words 1023 | > Facade pattern provides a simplified interface to a complex subsystem. 1024 | 1025 | Wikipedia says 1026 | > A facade is an object that provides a simplified interface to a larger body of code, such as a class library. 1027 | 1028 | **Programmatic Example** 1029 | 1030 | Taking our computer example from above. Here we have the computer class 1031 | 1032 | ```php 1033 | class Computer 1034 | { 1035 | public function getElectricShock() 1036 | { 1037 | echo "Ouch!"; 1038 | } 1039 | 1040 | public function makeSound() 1041 | { 1042 | echo "Beep beep!"; 1043 | } 1044 | 1045 | public function showLoadingScreen() 1046 | { 1047 | echo "Loading.."; 1048 | } 1049 | 1050 | public function bam() 1051 | { 1052 | echo "Ready to be used!"; 1053 | } 1054 | 1055 | public function closeEverything() 1056 | { 1057 | echo "Bup bup bup buzzzz!"; 1058 | } 1059 | 1060 | public function sooth() 1061 | { 1062 | echo "Zzzzz"; 1063 | } 1064 | 1065 | public function pullCurrent() 1066 | { 1067 | echo "Haaah!"; 1068 | } 1069 | } 1070 | ``` 1071 | Here we have the facade 1072 | ```php 1073 | class ComputerFacade 1074 | { 1075 | protected $computer; 1076 | 1077 | public function __construct(Computer $computer) 1078 | { 1079 | $this->computer = $computer; 1080 | } 1081 | 1082 | public function turnOn() 1083 | { 1084 | $this->computer->getElectricShock(); 1085 | $this->computer->makeSound(); 1086 | $this->computer->showLoadingScreen(); 1087 | $this->computer->bam(); 1088 | } 1089 | 1090 | public function turnOff() 1091 | { 1092 | $this->computer->closeEverything(); 1093 | $this->computer->pullCurrent(); 1094 | $this->computer->sooth(); 1095 | } 1096 | } 1097 | ``` 1098 | Now to use the facade 1099 | ```php 1100 | $computer = new ComputerFacade(new Computer()); 1101 | $computer->turnOn(); // Ouch! Beep beep! Loading.. Ready to be used! 1102 | $computer->turnOff(); // Bup bup buzzz! Haah! Zzzzz 1103 | ``` 1104 | 1105 | 🍃 Flyweight 1106 | --------- 1107 | 1108 | Real world example 1109 | > Did you ever have fresh tea from some stall? They often make more than one cup that you demanded and save the rest for any other customer so to save the resources e.g. gas etc. Flyweight pattern is all about that i.e. sharing. 1110 | 1111 | In plain words 1112 | > It is used to minimize memory usage or computational expenses by sharing as much as possible with similar objects. 1113 | 1114 | Wikipedia says 1115 | > In computer programming, flyweight is a software design pattern. A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory. 1116 | 1117 | **Programmatic example** 1118 | 1119 | Translating our tea example from above. First of all we have tea types and tea maker 1120 | 1121 | ```php 1122 | // Anything that will be cached is flyweight. 1123 | // Types of tea here will be flyweights. 1124 | class KarakTea 1125 | { 1126 | } 1127 | 1128 | // Acts as a factory and saves the tea 1129 | class TeaMaker 1130 | { 1131 | protected $availableTea = []; 1132 | 1133 | public function make($preference) 1134 | { 1135 | if (empty($this->availableTea[$preference])) { 1136 | $this->availableTea[$preference] = new KarakTea(); 1137 | } 1138 | 1139 | return $this->availableTea[$preference]; 1140 | } 1141 | } 1142 | ``` 1143 | 1144 | Then we have the `TeaShop` which takes orders and serves them 1145 | 1146 | ```php 1147 | class TeaShop 1148 | { 1149 | protected $orders; 1150 | protected $teaMaker; 1151 | 1152 | public function __construct(TeaMaker $teaMaker) 1153 | { 1154 | $this->teaMaker = $teaMaker; 1155 | } 1156 | 1157 | public function takeOrder(string $teaType, int $table) 1158 | { 1159 | $this->orders[$table] = $this->teaMaker->make($teaType); 1160 | } 1161 | 1162 | public function serve() 1163 | { 1164 | foreach ($this->orders as $table => $tea) { 1165 | echo "Serving tea to table# " . $table; 1166 | } 1167 | } 1168 | } 1169 | ``` 1170 | And it can be used as below 1171 | 1172 | ```php 1173 | $teaMaker = new TeaMaker(); 1174 | $shop = new TeaShop($teaMaker); 1175 | 1176 | $shop->takeOrder('less sugar', 1); 1177 | $shop->takeOrder('more milk', 2); 1178 | $shop->takeOrder('without sugar', 5); 1179 | 1180 | $shop->serve(); 1181 | // Serving tea to table# 1 1182 | // Serving tea to table# 2 1183 | // Serving tea to table# 5 1184 | ``` 1185 | 1186 | 🎱 Proxy 1187 | ------------------- 1188 | Real world example 1189 | > Have you ever used an access card to go through a door? There are multiple options to open that door i.e. it can be opened either using access card or by pressing a button that bypasses the security. The door's main functionality is to open but there is a proxy added on top of it to add some functionality. Let me better explain it using the code example below. 1190 | 1191 | In plain words 1192 | > Using the proxy pattern, a class represents the functionality of another class. 1193 | 1194 | Wikipedia says 1195 | > A proxy, in its most general form, is a class functioning as an interface to something else. A proxy is a wrapper or agent object that is being called by the client to access the real serving object behind the scenes. Use of the proxy can simply be forwarding to the real object, or can provide additional logic. In the proxy extra functionality can be provided, for example caching when operations on the real object are resource intensive, or checking preconditions before operations on the real object are invoked. 1196 | 1197 | **Programmatic Example** 1198 | 1199 | Taking our security door example from above. Firstly we have the door interface and an implementation of door 1200 | 1201 | ```php 1202 | interface Door 1203 | { 1204 | public function open(); 1205 | public function close(); 1206 | } 1207 | 1208 | class LabDoor implements Door 1209 | { 1210 | public function open() 1211 | { 1212 | echo "Opening lab door"; 1213 | } 1214 | 1215 | public function close() 1216 | { 1217 | echo "Closing the lab door"; 1218 | } 1219 | } 1220 | ``` 1221 | Then we have a proxy to secure any doors that we want 1222 | ```php 1223 | class Security 1224 | { 1225 | protected $door; 1226 | 1227 | public function __construct(Door $door) 1228 | { 1229 | $this->door = $door; 1230 | } 1231 | 1232 | public function open($password) 1233 | { 1234 | if ($this->authenticate($password)) { 1235 | $this->door->open(); 1236 | } else { 1237 | echo "Big no! It ain't possible."; 1238 | } 1239 | } 1240 | 1241 | public function authenticate($password) 1242 | { 1243 | return $password === '$ecr@t'; 1244 | } 1245 | 1246 | public function close() 1247 | { 1248 | $this->door->close(); 1249 | } 1250 | } 1251 | ``` 1252 | And here is how it can be used 1253 | ```php 1254 | $door = new Security(new LabDoor()); 1255 | $door->open('invalid'); // Big no! It ain't possible. 1256 | 1257 | $door->open('$ecr@t'); // Opening lab door 1258 | $door->close(); // Closing lab door 1259 | ``` 1260 | Yet another example would be some sort of data-mapper implementation. For example, I recently made an ODM (Object Data Mapper) for MongoDB using this pattern where I wrote a proxy around mongo classes while utilizing the magic method `__call()`. All the method calls were proxied to the original mongo class and result retrieved was returned as it is but in case of `find` or `findOne` data was mapped to the required class objects and the object was returned instead of `Cursor`. 1261 | 1262 | Behavioral Design Patterns 1263 | ========================== 1264 | 1265 | In plain words 1266 | > It is concerned with assignment of responsibilities between the objects. What makes them different from structural patterns is they don't just specify the structure but also outline the patterns for message passing/communication between them. Or in other words, they assist in answering "How to run a behavior in software component?" 1267 | 1268 | Wikipedia says 1269 | > In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication. 1270 | 1271 | * [Chain of Responsibility](#-chain-of-responsibility) 1272 | * [Command](#-command) 1273 | * [Iterator](#-iterator) 1274 | * [Mediator](#-mediator) 1275 | * [Memento](#-memento) 1276 | * [Observer](#-observer) 1277 | * [Visitor](#-visitor) 1278 | * [Strategy](#-strategy) 1279 | * [State](#-state) 1280 | * [Template Method](#-template-method) 1281 | 1282 | 🔗 Chain of Responsibility 1283 | ----------------------- 1284 | 1285 | Real world example 1286 | > For example, you have three payment methods (`A`, `B` and `C`) setup in your account; each having a different amount in it. `A` has 100 USD, `B` has 300 USD and `C` having 1000 USD and the preference for payments is chosen as `A` then `B` then `C`. You try to purchase something that is worth 210 USD. Using Chain of Responsibility, first of all account `A` will be checked if it can make the purchase, if yes purchase will be made and the chain will be broken. If not, request will move forward to account `B` checking for amount if yes chain will be broken otherwise the request will keep forwarding till it finds the suitable handler. Here `A`, `B` and `C` are links of the chain and the whole phenomenon is Chain of Responsibility. 1287 | 1288 | In plain words 1289 | > It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler. 1290 | 1291 | Wikipedia says 1292 | > In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. 1293 | 1294 | **Programmatic Example** 1295 | 1296 | Translating our account example above. First of all we have a base account having the logic for chaining the accounts together and some accounts 1297 | 1298 | ```php 1299 | abstract class Account 1300 | { 1301 | protected $successor; 1302 | protected $balance; 1303 | 1304 | public function setNext(Account $account) 1305 | { 1306 | $this->successor = $account; 1307 | } 1308 | 1309 | public function pay(float $amountToPay) 1310 | { 1311 | if ($this->canPay($amountToPay)) { 1312 | echo sprintf('Paid %s using %s' . PHP_EOL, $amountToPay, get_called_class()); 1313 | } elseif ($this->successor) { 1314 | echo sprintf('Cannot pay using %s. Proceeding ..' . PHP_EOL, get_called_class()); 1315 | $this->successor->pay($amountToPay); 1316 | } else { 1317 | throw new Exception('None of the accounts have enough balance'); 1318 | } 1319 | } 1320 | 1321 | public function canPay($amount): bool 1322 | { 1323 | return $this->balance >= $amount; 1324 | } 1325 | } 1326 | 1327 | class Bank extends Account 1328 | { 1329 | protected $balance; 1330 | 1331 | public function __construct(float $balance) 1332 | { 1333 | $this->balance = $balance; 1334 | } 1335 | } 1336 | 1337 | class Paypal extends Account 1338 | { 1339 | protected $balance; 1340 | 1341 | public function __construct(float $balance) 1342 | { 1343 | $this->balance = $balance; 1344 | } 1345 | } 1346 | 1347 | class Bitcoin extends Account 1348 | { 1349 | protected $balance; 1350 | 1351 | public function __construct(float $balance) 1352 | { 1353 | $this->balance = $balance; 1354 | } 1355 | } 1356 | ``` 1357 | 1358 | Now let's prepare the chain using the links defined above (i.e. Bank, Paypal, Bitcoin) 1359 | 1360 | ```php 1361 | // Let's prepare a chain like below 1362 | // $bank->$paypal->$bitcoin 1363 | // 1364 | // First priority bank 1365 | // If bank can't pay then paypal 1366 | // If paypal can't pay then bit coin 1367 | 1368 | $bank = new Bank(100); // Bank with balance 100 1369 | $paypal = new Paypal(200); // Paypal with balance 200 1370 | $bitcoin = new Bitcoin(300); // Bitcoin with balance 300 1371 | 1372 | $bank->setNext($paypal); 1373 | $paypal->setNext($bitcoin); 1374 | 1375 | // Let's try to pay using the first priority i.e. bank 1376 | $bank->pay(259); 1377 | 1378 | // Output will be 1379 | // ============== 1380 | // Cannot pay using bank. Proceeding .. 1381 | // Cannot pay using paypal. Proceeding ..: 1382 | // Paid 259 using Bitcoin! 1383 | ``` 1384 | 1385 | 👮 Command 1386 | ------- 1387 | 1388 | Real world example 1389 | > A generic example would be you ordering a food at restaurant. You (i.e. `Client`) ask the waiter (i.e. `Invoker`) to bring some food (i.e. `Command`) and waiter simply forwards the request to Chef (i.e. `Receiver`) who has the knowledge of what and how to cook. 1390 | > Another example would be you (i.e. `Client`) switching on (i.e. `Command`) the television (i.e. `Receiver`) using a remote control (`Invoker`). 1391 | 1392 | In plain words 1393 | > Allows you to encapsulate actions in objects. The key idea behind this pattern is to provide the means to decouple client from receiver. 1394 | 1395 | Wikipedia says 1396 | > In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters. 1397 | 1398 | **Programmatic Example** 1399 | 1400 | First of all we have the receiver that has the implementation of every action that could be performed 1401 | ```php 1402 | // Receiver 1403 | class Bulb 1404 | { 1405 | public function turnOn() 1406 | { 1407 | echo "Bulb has been lit"; 1408 | } 1409 | 1410 | public function turnOff() 1411 | { 1412 | echo "Darkness!"; 1413 | } 1414 | } 1415 | ``` 1416 | then we have an interface that each of the commands are going to implement and then we have a set of commands 1417 | ```php 1418 | interface Command 1419 | { 1420 | public function execute(); 1421 | public function undo(); 1422 | public function redo(); 1423 | } 1424 | 1425 | // Command 1426 | class TurnOn implements Command 1427 | { 1428 | protected $bulb; 1429 | 1430 | public function __construct(Bulb $bulb) 1431 | { 1432 | $this->bulb = $bulb; 1433 | } 1434 | 1435 | public function execute() 1436 | { 1437 | $this->bulb->turnOn(); 1438 | } 1439 | 1440 | public function undo() 1441 | { 1442 | $this->bulb->turnOff(); 1443 | } 1444 | 1445 | public function redo() 1446 | { 1447 | $this->execute(); 1448 | } 1449 | } 1450 | 1451 | class TurnOff implements Command 1452 | { 1453 | protected $bulb; 1454 | 1455 | public function __construct(Bulb $bulb) 1456 | { 1457 | $this->bulb = $bulb; 1458 | } 1459 | 1460 | public function execute() 1461 | { 1462 | $this->bulb->turnOff(); 1463 | } 1464 | 1465 | public function undo() 1466 | { 1467 | $this->bulb->turnOn(); 1468 | } 1469 | 1470 | public function redo() 1471 | { 1472 | $this->execute(); 1473 | } 1474 | } 1475 | ``` 1476 | Then we have an `Invoker` with whom the client will interact to process any commands 1477 | ```php 1478 | // Invoker 1479 | class RemoteControl 1480 | { 1481 | public function submit(Command $command) 1482 | { 1483 | $command->execute(); 1484 | } 1485 | } 1486 | ``` 1487 | Finally let's see how we can use it in our client 1488 | ```php 1489 | $bulb = new Bulb(); 1490 | 1491 | $turnOn = new TurnOn($bulb); 1492 | $turnOff = new TurnOff($bulb); 1493 | 1494 | $remote = new RemoteControl(); 1495 | $remote->submit($turnOn); // Bulb has been lit! 1496 | $remote->submit($turnOff); // Darkness! 1497 | ``` 1498 | 1499 | Command pattern can also be used to implement a transaction based system. Where you keep maintaining the history of commands as soon as you execute them. If the final command is successfully executed, all good otherwise just iterate through the history and keep executing the `undo` on all the executed commands. 1500 | 1501 | ➿ Iterator 1502 | -------- 1503 | 1504 | Real world example 1505 | > An old radio set will be a good example of iterator, where user could start at some channel and then use next or previous buttons to go through the respective channels. Or take an example of MP3 player or a TV set where you could press the next and previous buttons to go through the consecutive channels or in other words they all provide an interface to iterate through the respective channels, songs or radio stations. 1506 | 1507 | In plain words 1508 | > It presents a way to access the elements of an object without exposing the underlying presentation. 1509 | 1510 | Wikipedia says 1511 | > In object-oriented programming, the iterator pattern is a design pattern in which an iterator is used to traverse a container and access the container's elements. The iterator pattern decouples algorithms from containers; in some cases, algorithms are necessarily container-specific and thus cannot be decoupled. 1512 | 1513 | **Programmatic example** 1514 | 1515 | In PHP it is quite easy to implement using SPL (Standard PHP Library). Translating our radio stations example from above. First of all we have `RadioStation` 1516 | 1517 | ```php 1518 | class RadioStation 1519 | { 1520 | protected $frequency; 1521 | 1522 | public function __construct(float $frequency) 1523 | { 1524 | $this->frequency = $frequency; 1525 | } 1526 | 1527 | public function getFrequency(): float 1528 | { 1529 | return $this->frequency; 1530 | } 1531 | } 1532 | ``` 1533 | Then we have our iterator 1534 | 1535 | ```php 1536 | use Countable; 1537 | use Iterator; 1538 | 1539 | class StationList implements Countable, Iterator 1540 | { 1541 | /** @var RadioStation[] $stations */ 1542 | protected $stations = []; 1543 | 1544 | /** @var int $counter */ 1545 | protected $counter; 1546 | 1547 | public function addStation(RadioStation $station) 1548 | { 1549 | $this->stations[] = $station; 1550 | } 1551 | 1552 | public function removeStation(RadioStation $toRemove) 1553 | { 1554 | $toRemoveFrequency = $toRemove->getFrequency(); 1555 | $this->stations = array_filter($this->stations, function (RadioStation $station) use ($toRemoveFrequency) { 1556 | return $station->getFrequency() !== $toRemoveFrequency; 1557 | }); 1558 | } 1559 | 1560 | public function count(): int 1561 | { 1562 | return count($this->stations); 1563 | } 1564 | 1565 | public function current(): RadioStation 1566 | { 1567 | return $this->stations[$this->counter]; 1568 | } 1569 | 1570 | public function key() 1571 | { 1572 | return $this->counter; 1573 | } 1574 | 1575 | public function next() 1576 | { 1577 | $this->counter++; 1578 | } 1579 | 1580 | public function rewind() 1581 | { 1582 | $this->counter = 0; 1583 | } 1584 | 1585 | public function valid(): bool 1586 | { 1587 | return isset($this->stations[$this->counter]); 1588 | } 1589 | } 1590 | ``` 1591 | And then it can be used as 1592 | ```php 1593 | $stationList = new StationList(); 1594 | 1595 | $stationList->addStation(new RadioStation(89)); 1596 | $stationList->addStation(new RadioStation(101)); 1597 | $stationList->addStation(new RadioStation(102)); 1598 | $stationList->addStation(new RadioStation(103.2)); 1599 | 1600 | foreach($stationList as $station) { 1601 | echo $station->getFrequency() . PHP_EOL; 1602 | } 1603 | 1604 | $stationList->removeStation(new RadioStation(89)); // Will remove station 89 1605 | ``` 1606 | 1607 | 👽 Mediator 1608 | ======== 1609 | 1610 | Real world example 1611 | > A general example would be when you talk to someone on your mobile phone, there is a network provider sitting between you and them and your conversation goes through it instead of being directly sent. In this case network provider is mediator. 1612 | 1613 | In plain words 1614 | > Mediator pattern adds a third party object (called mediator) to control the interaction between two objects (called colleagues). It helps reduce the coupling between the classes communicating with each other. Because now they don't need to have the knowledge of each other's implementation. 1615 | 1616 | Wikipedia says 1617 | > In software engineering, the mediator pattern defines an object that encapsulates how a set of objects interact. This pattern is considered to be a behavioral pattern due to the way it can alter the program's running behavior. 1618 | 1619 | **Programmatic Example** 1620 | 1621 | Here is the simplest example of a chat room (i.e. mediator) with users (i.e. colleagues) sending messages to each other. 1622 | 1623 | First of all, we have the mediator i.e. the chat room 1624 | 1625 | ```php 1626 | interface ChatRoomMediator 1627 | { 1628 | public function showMessage(User $user, string $message); 1629 | } 1630 | 1631 | // Mediator 1632 | class ChatRoom implements ChatRoomMediator 1633 | { 1634 | public function showMessage(User $user, string $message) 1635 | { 1636 | $time = date('M d, y H:i'); 1637 | $sender = $user->getName(); 1638 | 1639 | echo $time . '[' . $sender . ']:' . $message; 1640 | } 1641 | } 1642 | ``` 1643 | 1644 | Then we have our users i.e. colleagues 1645 | ```php 1646 | class User { 1647 | protected $name; 1648 | protected $chatMediator; 1649 | 1650 | public function __construct(string $name, ChatRoomMediator $chatMediator) { 1651 | $this->name = $name; 1652 | $this->chatMediator = $chatMediator; 1653 | } 1654 | 1655 | public function getName() { 1656 | return $this->name; 1657 | } 1658 | 1659 | public function send($message) { 1660 | $this->chatMediator->showMessage($this, $message); 1661 | } 1662 | } 1663 | ``` 1664 | And the usage 1665 | ```php 1666 | $mediator = new ChatRoom(); 1667 | 1668 | $john = new User('John Doe', $mediator); 1669 | $jane = new User('Jane Doe', $mediator); 1670 | 1671 | $john->send('Hi there!'); 1672 | $jane->send('Hey!'); 1673 | 1674 | // Output will be 1675 | // Feb 14, 10:58 [John]: Hi there! 1676 | // Feb 14, 10:58 [Jane]: Hey! 1677 | ``` 1678 | 1679 | 💾 Memento 1680 | ------- 1681 | Real world example 1682 | > Take the example of calculator (i.e. originator), where whenever you perform some calculation the last calculation is saved in memory (i.e. memento) so that you can get back to it and maybe get it restored using some action buttons (i.e. caretaker). 1683 | 1684 | In plain words 1685 | > Memento pattern is about capturing and storing the current state of an object in a manner that it can be restored later on in a smooth manner. 1686 | 1687 | Wikipedia says 1688 | > The memento pattern is a software design pattern that provides the ability to restore an object to its previous state (undo via rollback). 1689 | 1690 | Usually useful when you need to provide some sort of undo functionality. 1691 | 1692 | **Programmatic Example** 1693 | 1694 | Lets take an example of text editor which keeps saving the state from time to time and that you can restore if you want. 1695 | 1696 | First of all we have our memento object that will be able to hold the editor state 1697 | 1698 | ```php 1699 | class EditorMemento 1700 | { 1701 | protected $content; 1702 | 1703 | public function __construct(string $content) 1704 | { 1705 | $this->content = $content; 1706 | } 1707 | 1708 | public function getContent() 1709 | { 1710 | return $this->content; 1711 | } 1712 | } 1713 | ``` 1714 | 1715 | Then we have our editor i.e. originator that is going to use memento object 1716 | 1717 | ```php 1718 | class Editor 1719 | { 1720 | protected $content = ''; 1721 | 1722 | public function type(string $words) 1723 | { 1724 | $this->content = $this->content . ' ' . $words; 1725 | } 1726 | 1727 | public function getContent() 1728 | { 1729 | return $this->content; 1730 | } 1731 | 1732 | public function save() 1733 | { 1734 | return new EditorMemento($this->content); 1735 | } 1736 | 1737 | public function restore(EditorMemento $memento) 1738 | { 1739 | $this->content = $memento->getContent(); 1740 | } 1741 | } 1742 | ``` 1743 | 1744 | And then it can be used as 1745 | 1746 | ```php 1747 | $editor = new Editor(); 1748 | 1749 | // Type some stuff 1750 | $editor->type('This is the first sentence.'); 1751 | $editor->type('This is second.'); 1752 | 1753 | // Save the state to restore to : This is the first sentence. This is second. 1754 | $saved = $editor->save(); 1755 | 1756 | // Type some more 1757 | $editor->type('And this is third.'); 1758 | 1759 | // Output: Content before Saving 1760 | echo $editor->getContent(); // This is the first sentence. This is second. And this is third. 1761 | 1762 | // Restoring to last saved state 1763 | $editor->restore($saved); 1764 | 1765 | $editor->getContent(); // This is the first sentence. This is second. 1766 | ``` 1767 | 1768 | 😎 Observer 1769 | -------- 1770 | Real world example 1771 | > A good example would be the job seekers where they subscribe to some job posting site and they are notified whenever there is a matching job opportunity. 1772 | 1773 | In plain words 1774 | > Defines a dependency between objects so that whenever an object changes its state, all its dependents are notified. 1775 | 1776 | Wikipedia says 1777 | > The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. 1778 | 1779 | **Programmatic example** 1780 | 1781 | Translating our example from above. First of all we have job seekers that need to be notified for a job posting 1782 | ```php 1783 | class JobPost 1784 | { 1785 | protected $title; 1786 | 1787 | public function __construct(string $title) 1788 | { 1789 | $this->title = $title; 1790 | } 1791 | 1792 | public function getTitle() 1793 | { 1794 | return $this->title; 1795 | } 1796 | } 1797 | 1798 | class JobSeeker implements Observer 1799 | { 1800 | protected $name; 1801 | 1802 | public function __construct(string $name) 1803 | { 1804 | $this->name = $name; 1805 | } 1806 | 1807 | public function onJobPosted(JobPost $job) 1808 | { 1809 | // Do something with the job posting 1810 | echo 'Hi ' . $this->name . '! New job posted: '. $job->getTitle(); 1811 | } 1812 | } 1813 | ``` 1814 | Then we have our job postings to which the job seekers will subscribe 1815 | ```php 1816 | class JobPostings implements Observable 1817 | { 1818 | protected $observers = []; 1819 | 1820 | protected function notify(JobPost $jobPosting) 1821 | { 1822 | foreach ($this->observers as $observer) { 1823 | $observer->onJobPosted($jobPosting); 1824 | } 1825 | } 1826 | 1827 | public function attach(Observer $observer) 1828 | { 1829 | $this->observers[] = $observer; 1830 | } 1831 | 1832 | public function addJob(JobPost $jobPosting) 1833 | { 1834 | $this->notify($jobPosting); 1835 | } 1836 | } 1837 | ``` 1838 | Then it can be used as 1839 | ```php 1840 | // Create subscribers 1841 | $johnDoe = new JobSeeker('John Doe'); 1842 | $janeDoe = new JobSeeker('Jane Doe'); 1843 | 1844 | // Create publisher and attach subscribers 1845 | $jobPostings = new JobPostings(); 1846 | $jobPostings->attach($johnDoe); 1847 | $jobPostings->attach($janeDoe); 1848 | 1849 | // Add a new job and see if subscribers get notified 1850 | $jobPostings->addJob(new JobPost('Software Engineer')); 1851 | 1852 | // Output 1853 | // Hi John Doe! New job posted: Software Engineer 1854 | // Hi Jane Doe! New job posted: Software Engineer 1855 | ``` 1856 | 1857 | 🏃 Visitor 1858 | ------- 1859 | Real world example 1860 | > Consider someone visiting Dubai. They just need a way (i.e. visa) to enter Dubai. After arrival, they can come and visit any place in Dubai on their own without having to ask for permission or to do some leg work in order to visit any place here; just let them know of a place and they can visit it. Visitor pattern lets you do just that, it helps you add places to visit so that they can visit as much as they can without having to do any legwork. 1861 | 1862 | In plain words 1863 | > Visitor pattern lets you add further operations to objects without having to modify them. 1864 | 1865 | Wikipedia says 1866 | > In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures. It is one way to follow the open/closed principle. 1867 | 1868 | **Programmatic example** 1869 | 1870 | Let's take an example of a zoo simulation where we have several different kinds of animals and we have to make them Sound. Let's translate this using visitor pattern 1871 | 1872 | ```php 1873 | // Visitee 1874 | interface Animal 1875 | { 1876 | public function accept(AnimalOperation $operation); 1877 | } 1878 | 1879 | // Visitor 1880 | interface AnimalOperation 1881 | { 1882 | public function visitMonkey(Monkey $monkey); 1883 | public function visitLion(Lion $lion); 1884 | public function visitDolphin(Dolphin $dolphin); 1885 | } 1886 | ``` 1887 | Then we have our implementations for the animals 1888 | ```php 1889 | class Monkey implements Animal 1890 | { 1891 | public function shout() 1892 | { 1893 | echo 'Ooh oo aa aa!'; 1894 | } 1895 | 1896 | public function accept(AnimalOperation $operation) 1897 | { 1898 | $operation->visitMonkey($this); 1899 | } 1900 | } 1901 | 1902 | class Lion implements Animal 1903 | { 1904 | public function roar() 1905 | { 1906 | echo 'Roaaar!'; 1907 | } 1908 | 1909 | public function accept(AnimalOperation $operation) 1910 | { 1911 | $operation->visitLion($this); 1912 | } 1913 | } 1914 | 1915 | class Dolphin implements Animal 1916 | { 1917 | public function speak() 1918 | { 1919 | echo 'Tuut tuttu tuutt!'; 1920 | } 1921 | 1922 | public function accept(AnimalOperation $operation) 1923 | { 1924 | $operation->visitDolphin($this); 1925 | } 1926 | } 1927 | ``` 1928 | Let's implement our visitor 1929 | ```php 1930 | class Speak implements AnimalOperation 1931 | { 1932 | public function visitMonkey(Monkey $monkey) 1933 | { 1934 | $monkey->shout(); 1935 | } 1936 | 1937 | public function visitLion(Lion $lion) 1938 | { 1939 | $lion->roar(); 1940 | } 1941 | 1942 | public function visitDolphin(Dolphin $dolphin) 1943 | { 1944 | $dolphin->speak(); 1945 | } 1946 | } 1947 | ``` 1948 | 1949 | And then it can be used as 1950 | ```php 1951 | $monkey = new Monkey(); 1952 | $lion = new Lion(); 1953 | $dolphin = new Dolphin(); 1954 | 1955 | $speak = new Speak(); 1956 | 1957 | $monkey->accept($speak); // Ooh oo aa aa! 1958 | $lion->accept($speak); // Roaaar! 1959 | $dolphin->accept($speak); // Tuut tutt tuutt! 1960 | ``` 1961 | We could have done this simply by having a inheritance hierarchy for the animals but then we would have to modify the animals whenever we would have to add new actions to animals. But now we will not have to change them. For example, let's say we are asked to add the jump behavior to the animals, we can simply add that by creating a new visitor i.e. 1962 | 1963 | ```php 1964 | class Jump implements AnimalOperation 1965 | { 1966 | public function visitMonkey(Monkey $monkey) 1967 | { 1968 | echo 'Jumped 20 feet high! on to the tree!'; 1969 | } 1970 | 1971 | public function visitLion(Lion $lion) 1972 | { 1973 | echo 'Jumped 7 feet! Back on the ground!'; 1974 | } 1975 | 1976 | public function visitDolphin(Dolphin $dolphin) 1977 | { 1978 | echo 'Walked on water a little and disappeared'; 1979 | } 1980 | } 1981 | ``` 1982 | And for the usage 1983 | ```php 1984 | $jump = new Jump(); 1985 | 1986 | $monkey->accept($speak); // Ooh oo aa aa! 1987 | $monkey->accept($jump); // Jumped 20 feet high! on to the tree! 1988 | 1989 | $lion->accept($speak); // Roaaar! 1990 | $lion->accept($jump); // Jumped 7 feet! Back on the ground! 1991 | 1992 | $dolphin->accept($speak); // Tuut tutt tuutt! 1993 | $dolphin->accept($jump); // Walked on water a little and disappeared 1994 | ``` 1995 | 1996 | 💡 Strategy 1997 | -------- 1998 | 1999 | Real world example 2000 | > Consider the example of sorting, we implemented bubble sort but the data started to grow and bubble sort started getting very slow. In order to tackle this we implemented Quick sort. But now although the quick sort algorithm was doing better for large datasets, it was very slow for smaller datasets. In order to handle this we implemented a strategy where for small datasets, bubble sort will be used and for larger, quick sort. 2001 | 2002 | In plain words 2003 | > Strategy pattern allows you to switch the algorithm or strategy based upon the situation. 2004 | 2005 | Wikipedia says 2006 | > In computer programming, the strategy pattern (also known as the policy pattern) is a behavioural software design pattern that enables an algorithm's behavior to be selected at runtime. 2007 | 2008 | **Programmatic example** 2009 | 2010 | Translating our example from above. First of all we have our strategy interface and different strategy implementations 2011 | 2012 | ```php 2013 | interface SortStrategy 2014 | { 2015 | public function sort(array $dataset): array; 2016 | } 2017 | 2018 | class BubbleSortStrategy implements SortStrategy 2019 | { 2020 | public function sort(array $dataset): array 2021 | { 2022 | echo "Sorting using bubble sort"; 2023 | 2024 | // Do sorting 2025 | return $dataset; 2026 | } 2027 | } 2028 | 2029 | class QuickSortStrategy implements SortStrategy 2030 | { 2031 | public function sort(array $dataset): array 2032 | { 2033 | echo "Sorting using quick sort"; 2034 | 2035 | // Do sorting 2036 | return $dataset; 2037 | } 2038 | } 2039 | ``` 2040 | 2041 | And then we have our client that is going to use any strategy 2042 | ```php 2043 | class Sorter 2044 | { 2045 | protected $sorter; 2046 | 2047 | public function __construct(SortStrategy $sorter) 2048 | { 2049 | $this->sorter = $sorter; 2050 | } 2051 | 2052 | public function sort(array $dataset): array 2053 | { 2054 | return $this->sorter->sort($dataset); 2055 | } 2056 | } 2057 | ``` 2058 | And it can be used as 2059 | ```php 2060 | $dataset = [1, 5, 4, 3, 2, 8]; 2061 | 2062 | $sorter = new Sorter(new BubbleSortStrategy()); 2063 | $sorter->sort($dataset); // Output : Sorting using bubble sort 2064 | 2065 | $sorter = new Sorter(new QuickSortStrategy()); 2066 | $sorter->sort($dataset); // Output : Sorting using quick sort 2067 | ``` 2068 | 2069 | 💢 State 2070 | ----- 2071 | Real world example 2072 | > Imagine you are using some drawing application, you choose the paint brush to draw. Now the brush changes its behavior based on the selected color i.e. if you have chosen red color it will draw in red, if blue then it will be in blue etc. 2073 | 2074 | In plain words 2075 | > It lets you change the behavior of a class when the state changes. 2076 | 2077 | Wikipedia says 2078 | > The state pattern is a behavioral software design pattern that implements a state machine in an object-oriented way. With the state pattern, a state machine is implemented by implementing each individual state as a derived class of the state pattern interface, and implementing state transitions by invoking methods defined by the pattern's superclass. 2079 | > The state pattern can be interpreted as a strategy pattern which is able to switch the current strategy through invocations of methods defined in the pattern's interface. 2080 | 2081 | **Programmatic example** 2082 | 2083 | Let's take an example of text editor, it lets you change the state of text that is typed i.e. if you have selected bold, it starts writing in bold, if italic then in italics etc. 2084 | 2085 | First of all we have our state interface and some state implementations 2086 | 2087 | ```php 2088 | interface WritingState 2089 | { 2090 | public function write(string $words); 2091 | } 2092 | 2093 | class UpperCase implements WritingState 2094 | { 2095 | public function write(string $words) 2096 | { 2097 | echo strtoupper($words); 2098 | } 2099 | } 2100 | 2101 | class LowerCase implements WritingState 2102 | { 2103 | public function write(string $words) 2104 | { 2105 | echo strtolower($words); 2106 | } 2107 | } 2108 | 2109 | class Default implements WritingState 2110 | { 2111 | public function write(string $words) 2112 | { 2113 | echo $words; 2114 | } 2115 | } 2116 | ``` 2117 | Then we have our editor 2118 | ```php 2119 | class TextEditor 2120 | { 2121 | protected $state; 2122 | 2123 | public function __construct(WritingState $state) 2124 | { 2125 | $this->state = $state; 2126 | } 2127 | 2128 | public function setState(WritingState $state) 2129 | { 2130 | $this->state = $state; 2131 | } 2132 | 2133 | public function type(string $words) 2134 | { 2135 | $this->state->write($words); 2136 | } 2137 | } 2138 | ``` 2139 | And then it can be used as 2140 | ```php 2141 | $editor = new TextEditor(new Default()); 2142 | 2143 | $editor->type('First line'); 2144 | 2145 | $editor->setState(new UpperCase()); 2146 | 2147 | $editor->type('Second line'); 2148 | $editor->type('Third line'); 2149 | 2150 | $editor->setState(new LowerCase()); 2151 | 2152 | $editor->type('Fourth line'); 2153 | $editor->type('Fifth line'); 2154 | 2155 | // Output: 2156 | // First line 2157 | // SECOND LINE 2158 | // THIRD LINE 2159 | // fourth line 2160 | // fifth line 2161 | ``` 2162 | 2163 | 📒 Template Method 2164 | --------------- 2165 | 2166 | Real world example 2167 | > Suppose we are getting some house built. The steps for building might look like 2168 | > - Prepare the base of house 2169 | > - Build the walls 2170 | > - Add roof 2171 | > - Add other floors 2172 | 2173 | > The order of these steps could never be changed i.e. you can't build the roof before building the walls etc but each of the steps could be modified for example walls can be made of wood or polyester or stone. 2174 | 2175 | In plain words 2176 | > Template method defines the skeleton of how a certain algorithm could be performed, but defers the implementation of those steps to the children classes. 2177 | 2178 | Wikipedia says 2179 | > In software engineering, the template method pattern is a behavioral design pattern that defines the program skeleton of an algorithm in an operation, deferring some steps to subclasses. It lets one redefine certain steps of an algorithm without changing the algorithm's structure. 2180 | 2181 | **Programmatic Example** 2182 | 2183 | Imagine we have a build tool that helps us test, lint, build, generate build reports (i.e. code coverage reports, linting report etc) and deploy our app on the test server. 2184 | 2185 | First of all we have our base class that specifies the skeleton for the build algorithm 2186 | ```php 2187 | abstract class Builder 2188 | { 2189 | 2190 | // Template method 2191 | final public function build() 2192 | { 2193 | $this->test(); 2194 | $this->lint(); 2195 | $this->assemble(); 2196 | $this->deploy(); 2197 | } 2198 | 2199 | abstract public function test(); 2200 | abstract public function lint(); 2201 | abstract public function assemble(); 2202 | abstract public function deploy(); 2203 | } 2204 | ``` 2205 | 2206 | Then we can have our implementations 2207 | 2208 | ```php 2209 | class AndroidBuilder extends Builder 2210 | { 2211 | public function test() 2212 | { 2213 | echo 'Running android tests'; 2214 | } 2215 | 2216 | public function lint() 2217 | { 2218 | echo 'Linting the android code'; 2219 | } 2220 | 2221 | public function assemble() 2222 | { 2223 | echo 'Assembling the android build'; 2224 | } 2225 | 2226 | public function deploy() 2227 | { 2228 | echo 'Deploying android build to server'; 2229 | } 2230 | } 2231 | 2232 | class IosBuilder extends Builder 2233 | { 2234 | public function test() 2235 | { 2236 | echo 'Running ios tests'; 2237 | } 2238 | 2239 | public function lint() 2240 | { 2241 | echo 'Linting the ios code'; 2242 | } 2243 | 2244 | public function assemble() 2245 | { 2246 | echo 'Assembling the ios build'; 2247 | } 2248 | 2249 | public function deploy() 2250 | { 2251 | echo 'Deploying ios build to server'; 2252 | } 2253 | } 2254 | ``` 2255 | And then it can be used as 2256 | 2257 | ```php 2258 | $androidBuilder = new AndroidBuilder(); 2259 | $androidBuilder->build(); 2260 | 2261 | // Output: 2262 | // Running android tests 2263 | // Linting the android code 2264 | // Assembling the android build 2265 | // Deploying android build to server 2266 | 2267 | $iosBuilder = new IosBuilder(); 2268 | $iosBuilder->build(); 2269 | 2270 | // Output: 2271 | // Running ios tests 2272 | // Linting the ios code 2273 | // Assembling the ios build 2274 | // Deploying ios build to server 2275 | ``` 2276 | 2277 | ## 🚦 Wrap Up Folks 2278 | 2279 | And that about wraps it up. I will continue to improve this, so you might want to watch/star this repository to revisit. Also, I have plans on writing the same about the architectural patterns, stay tuned for it. 2280 | 2281 | ## 👬 Contribution 2282 | 2283 | - Report issues 2284 | - Open pull request with improvements 2285 | - Spread the word 2286 | - Reach out to me directly at kamranahmed.se@gmail.com or on twitter [@kamranahmedse](http://twitter.com/kamranahmedse) 2287 | 2288 | ## License 2289 | MIT © [Kamran Ahmed](http://kamranahmed.info) 2290 | -------------------------------------------------------------------------------- /README_en.md: -------------------------------------------------------------------------------- 1 | ![Design Patterns For Humans](https://cloud.githubusercontent.com/assets/11269635/23065273/1b7e5938-f515-11e6-8dd3-d0d58de6bb9a.png) 2 | 3 | *** 4 |

5 | 🎉 Ultra-simplified explanation to design patterns! 🎉 6 |

7 |

8 | A topic that can easily make anyone's mind wobble. Here I try to make them stick in to your mind (and maybe mine) by explaining them in the simplest way possible. 9 |

10 | *** 11 | 12 | 🚀 Introduction 13 | ================= 14 | 15 | Design patterns are solutions to recurring problems; **guidelines on how to tackle certain problems**. They are not classes, packages or libraries that you can plug into your application and wait for the magic to happen. These are, rather, guidelines on how to tackle certain problems in certain situations. 16 | 17 | > Design patterns are solutions to recurring problems; guidelines on how to tackle certain problems 18 | 19 | Wikipedia describes them as 20 | 21 | > In software engineering, a software design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. It is not a finished design that can be transformed directly into source or machine code. It is a description or template for how to solve a problem that can be used in many different situations. 22 | 23 | ⚠️ Be Careful 24 | ----------------- 25 | - Design patterns are not a silver bullet to all your problems. 26 | - Do not try to force them; bad things are supposed to happen, if done so. Keep in mind that design patterns are solutions **to** problems, not solutions **finding** problems; so don't overthink. 27 | - If used in a correct place in a correct manner, they can prove to be a savior; or else they can result in a horrible mess of a code. 28 | 29 | > Also note that the code samples below are in PHP-7, however this shouldn't stop you because the concepts are same anyways. Plus the **support for other languages is underway**. 30 | 31 | Types of Design Patterns 32 | ----------------- 33 | 34 | * [Creational](#creational-design-patterns) 35 | * [Structural](#structural-design-patterns) 36 | * [Behavioral](#behavioral-design-patterns) 37 | 38 | Creational Design Patterns 39 | ========================== 40 | 41 | In plain words 42 | > Creational patterns are focused towards how to instantiate an object or group of related objects. 43 | 44 | Wikipedia says 45 | > In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation. 46 | 47 | * [Simple Factory](#-simple-factory) 48 | * [Factory Method](#-factory-method) 49 | * [Abstract Factory](#-abstract-factory) 50 | * [Builder](#-builder) 51 | * [Prototype](#-prototype) 52 | * [Singleton](#-singleton) 53 | 54 | 🏠 Simple Factory 55 | -------------- 56 | Real world example 57 | > Consider, you are building a house and you need doors. It would be a mess if every time you need a door, you put on your carpenter clothes and start making a door in your house. Instead you get it made from a factory. 58 | 59 | In plain words 60 | > Simple factory simply generates an instance for client without exposing any instantiation logic to the client 61 | 62 | Wikipedia says 63 | > In object-oriented programming (OOP), a factory is an object for creating other objects – formally a factory is a function or method that returns objects of a varying prototype or class from some method call, which is assumed to be "new". 64 | 65 | **Programmatic Example** 66 | 67 | First of all we have a door interface and the implementation 68 | ```php 69 | interface Door 70 | { 71 | public function getWidth(): float; 72 | public function getHeight(): float; 73 | } 74 | 75 | class WoodenDoor implements Door 76 | { 77 | protected $width; 78 | protected $height; 79 | 80 | public function __construct(float $width, float $height) 81 | { 82 | $this->width = $width; 83 | $this->height = $height; 84 | } 85 | 86 | public function getWidth(): float 87 | { 88 | return $this->width; 89 | } 90 | 91 | public function getHeight(): float 92 | { 93 | return $this->height; 94 | } 95 | } 96 | ``` 97 | Then we have our door factory that makes the door and returns it 98 | ```php 99 | class DoorFactory 100 | { 101 | public static function makeDoor($width, $height): Door 102 | { 103 | return new WoodenDoor($width, $height); 104 | } 105 | } 106 | ``` 107 | And then it can be used as 108 | ```php 109 | $door = DoorFactory::makeDoor(100, 200); 110 | echo 'Width: ' . $door->getWidth(); 111 | echo 'Height: ' . $door->getHeight(); 112 | ``` 113 | 114 | **When to Use?** 115 | 116 | When creating an object is not just a few assignments and involves some logic, it makes sense to put it in a dedicated factory instead of repeating the same code everywhere. 117 | 118 | 🏭 Factory Method 119 | -------------- 120 | 121 | Real world example 122 | > Consider the case of a hiring manager. It is impossible for one person to interview for each of the positions. Based on the job opening, she has to decide and delegate the interview steps to different people. 123 | 124 | In plain words 125 | > It provides a way to delegate the instantiation logic to child classes. 126 | 127 | Wikipedia says 128 | > In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor. 129 | 130 | **Programmatic Example** 131 | 132 | Taking our hiring manager example above. First of all we have an interviewer interface and some implementations for it 133 | 134 | ```php 135 | interface Interviewer 136 | { 137 | public function askQuestions(); 138 | } 139 | 140 | class Developer implements Interviewer 141 | { 142 | public function askQuestions() 143 | { 144 | echo 'Asking about design patterns!'; 145 | } 146 | } 147 | 148 | class CommunityExecutive implements Interviewer 149 | { 150 | public function askQuestions() 151 | { 152 | echo 'Asking about community building'; 153 | } 154 | } 155 | ``` 156 | 157 | Now let us create our `HiringManager` 158 | 159 | ```php 160 | abstract class HiringManager 161 | { 162 | 163 | // Factory method 164 | abstract public function makeInterviewer(): Interviewer; 165 | 166 | public function takeInterview() 167 | { 168 | $interviewer = $this->makeInterviewer(); 169 | $interviewer->askQuestions(); 170 | } 171 | } 172 | 173 | ``` 174 | Now any child can extend it and provide the required interviewer 175 | ```php 176 | class DevelopmentManager extends HiringManager 177 | { 178 | public function makeInterviewer(): Interviewer 179 | { 180 | return new Developer(); 181 | } 182 | } 183 | 184 | class MarketingManager extends HiringManager 185 | { 186 | public function makeInterviewer(): Interviewer 187 | { 188 | return new CommunityExecutive(); 189 | } 190 | } 191 | ``` 192 | and then it can be used as 193 | 194 | ```php 195 | $devManager = new DevelopmentManager(); 196 | $devManager->takeInterview(); // Output: Asking about design patterns 197 | 198 | $marketingManager = new MarketingManager(); 199 | $marketingManager->takeInterview(); // Output: Asking about community building. 200 | ``` 201 | 202 | **When to use?** 203 | 204 | Useful when there is some generic processing in a class but the required sub-class is dynamically decided at runtime. Or putting it in other words, when the client doesn't know what exact sub-class it might need. 205 | 206 | 🔨 Abstract Factory 207 | ---------------- 208 | 209 | Real world example 210 | > Extending our door example from Simple Factory. Based on your needs you might get a wooden door from a wooden door shop, iron door from an iron shop or a PVC door from the relevant shop. Plus you might need a guy with different kind of specialities to fit the door, for example a carpenter for wooden door, welder for iron door etc. As you can see there is a dependency between the doors now, wooden door needs carpenter, iron door needs a welder etc. 211 | 212 | In plain words 213 | > A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes. 214 | 215 | Wikipedia says 216 | > The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes 217 | 218 | **Programmatic Example** 219 | 220 | Translating the door example above. First of all we have our `Door` interface and some implementation for it 221 | 222 | ```php 223 | interface Door 224 | { 225 | public function getDescription(); 226 | } 227 | 228 | class WoodenDoor implements Door 229 | { 230 | public function getDescription() 231 | { 232 | echo 'I am a wooden door'; 233 | } 234 | } 235 | 236 | class IronDoor implements Door 237 | { 238 | public function getDescription() 239 | { 240 | echo 'I am an iron door'; 241 | } 242 | } 243 | ``` 244 | Then we have some fitting experts for each door type 245 | 246 | ```php 247 | interface DoorFittingExpert 248 | { 249 | public function getDescription(); 250 | } 251 | 252 | class Welder implements DoorFittingExpert 253 | { 254 | public function getDescription() 255 | { 256 | echo 'I can only fit iron doors'; 257 | } 258 | } 259 | 260 | class Carpenter implements DoorFittingExpert 261 | { 262 | public function getDescription() 263 | { 264 | echo 'I can only fit wooden doors'; 265 | } 266 | } 267 | ``` 268 | 269 | Now we have our abstract factory that would let us make family of related objects i.e. wooden door factory would create a wooden door and wooden door fitting expert and iron door factory would create an iron door and iron door fitting expert 270 | ```php 271 | interface DoorFactory 272 | { 273 | public function makeDoor(): Door; 274 | public function makeFittingExpert(): DoorFittingExpert; 275 | } 276 | 277 | // Wooden factory to return carpenter and wooden door 278 | class WoodenDoorFactory implements DoorFactory 279 | { 280 | public function makeDoor(): Door 281 | { 282 | return new WoodenDoor(); 283 | } 284 | 285 | public function makeFittingExpert(): DoorFittingExpert 286 | { 287 | return new Carpenter(); 288 | } 289 | } 290 | 291 | // Iron door factory to get iron door and the relevant fitting expert 292 | class IronDoorFactory implements DoorFactory 293 | { 294 | public function makeDoor(): Door 295 | { 296 | return new IronDoor(); 297 | } 298 | 299 | public function makeFittingExpert(): DoorFittingExpert 300 | { 301 | return new Welder(); 302 | } 303 | } 304 | ``` 305 | And then it can be used as 306 | ```php 307 | $woodenFactory = new WoodenDoorFactory(); 308 | 309 | $door = $woodenFactory->makeDoor(); 310 | $expert = $woodenFactory->makeFittingExpert(); 311 | 312 | $door->getDescription(); // Output: I am a wooden door 313 | $expert->getDescription(); // Output: I can only fit wooden doors 314 | 315 | // Same for Iron Factory 316 | $ironFactory = new IronDoorFactory(); 317 | 318 | $door = $ironFactory->makeDoor(); 319 | $expert = $ironFactory->makeFittingExpert(); 320 | 321 | $door->getDescription(); // Output: I am an iron door 322 | $expert->getDescription(); // Output: I can only fit iron doors 323 | ``` 324 | 325 | As you can see the wooden door factory has encapsulated the `carpenter` and the `wooden door` also iron door factory has encapsulated the `iron door` and `welder`. And thus it had helped us make sure that for each of the created door, we do not get a wrong fitting expert. 326 | 327 | **When to use?** 328 | 329 | When there are interrelated dependencies with not-that-simple creation logic involved 330 | 331 | 👷 Builder 332 | -------------------------------------------- 333 | Real world example 334 | > Imagine you are at Hardee's and you order a specific deal, lets say, "Big Hardee" and they hand it over to you without *any questions*; this is the example of simple factory. But there are cases when the creation logic might involve more steps. For example you want a customized Subway deal, you have several options in how your burger is made e.g what bread do you want? what types of sauces would you like? What cheese would you want? etc. In such cases builder pattern comes to the rescue. 335 | 336 | In plain words 337 | > Allows you to create different flavors of an object while avoiding constructor pollution. Useful when there could be several flavors of an object. Or when there are a lot of steps involved in creation of an object. 338 | 339 | Wikipedia says 340 | > The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor anti-pattern. 341 | 342 | Having said that let me add a bit about what telescoping constructor anti-pattern is. At one point or the other we have all seen a constructor like below: 343 | 344 | ```php 345 | public function __construct($size, $cheese = true, $pepperoni = true, $tomato = false, $lettuce = true) 346 | { 347 | } 348 | ``` 349 | 350 | As you can see; the number of constructor parameters can quickly get out of hand and it might become difficult to understand the arrangement of parameters. Plus this parameter list could keep on growing if you would want to add more options in future. This is called telescoping constructor anti-pattern. 351 | 352 | **Programmatic Example** 353 | 354 | The sane alternative is to use the builder pattern. First of all we have our burger that we want to make 355 | 356 | ```php 357 | class Burger 358 | { 359 | protected $size; 360 | 361 | protected $cheese = false; 362 | protected $pepperoni = false; 363 | protected $lettuce = false; 364 | protected $tomato = false; 365 | 366 | public function __construct(BurgerBuilder $builder) 367 | { 368 | $this->size = $builder->size; 369 | $this->cheese = $builder->cheese; 370 | $this->pepperoni = $builder->pepperoni; 371 | $this->lettuce = $builder->lettuce; 372 | $this->tomato = $builder->tomato; 373 | } 374 | } 375 | ``` 376 | 377 | And then we have the builder 378 | 379 | ```php 380 | class BurgerBuilder 381 | { 382 | public $size; 383 | 384 | public $cheese = false; 385 | public $pepperoni = false; 386 | public $lettuce = false; 387 | public $tomato = false; 388 | 389 | public function __construct(int $size) 390 | { 391 | $this->size = $size; 392 | } 393 | 394 | public function addPepperoni() 395 | { 396 | $this->pepperoni = true; 397 | return $this; 398 | } 399 | 400 | public function addLettuce() 401 | { 402 | $this->lettuce = true; 403 | return $this; 404 | } 405 | 406 | public function addCheese() 407 | { 408 | $this->cheese = true; 409 | return $this; 410 | } 411 | 412 | public function addTomato() 413 | { 414 | $this->tomato = true; 415 | return $this; 416 | } 417 | 418 | public function build(): Burger 419 | { 420 | return new Burger($this); 421 | } 422 | } 423 | ``` 424 | And then it can be used as: 425 | 426 | ```php 427 | $burger = (new BurgerBuilder(14)) 428 | ->addPepperoni() 429 | ->addLettuce() 430 | ->addTomato() 431 | ->build(); 432 | ``` 433 | 434 | **When to use?** 435 | 436 | When there could be several flavors of an object and to avoid the constructor telescoping. The key difference from the factory pattern is that; factory pattern is to be used when the creation is a one step process while builder pattern is to be used when the creation is a multi step process. 437 | 438 | 🐑 Prototype 439 | ------------ 440 | Real world example 441 | > Remember dolly? The sheep that was cloned! Lets not get into the details but the key point here is that it is all about cloning 442 | 443 | In plain words 444 | > Create object based on an existing object through cloning. 445 | 446 | Wikipedia says 447 | > The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. 448 | 449 | In short, it allows you to create a copy of an existing object and modify it to your needs, instead of going through the trouble of creating an object from scratch and setting it up. 450 | 451 | **Programmatic Example** 452 | 453 | In PHP, it can be easily done using `clone` 454 | 455 | ```php 456 | class Sheep 457 | { 458 | protected $name; 459 | protected $category; 460 | 461 | public function __construct(string $name, string $category = 'Mountain Sheep') 462 | { 463 | $this->name = $name; 464 | $this->category = $category; 465 | } 466 | 467 | public function setName(string $name) 468 | { 469 | $this->name = $name; 470 | } 471 | 472 | public function getName() 473 | { 474 | return $this->name; 475 | } 476 | 477 | public function setCategory(string $category) 478 | { 479 | $this->category = $category; 480 | } 481 | 482 | public function getCategory() 483 | { 484 | return $this->category; 485 | } 486 | } 487 | ``` 488 | Then it can be cloned like below 489 | ```php 490 | $original = new Sheep('Jolly'); 491 | echo $original->getName(); // Jolly 492 | echo $original->getCategory(); // Mountain Sheep 493 | 494 | // Clone and modify what is required 495 | $cloned = clone $original; 496 | $cloned->setName('Dolly'); 497 | echo $cloned->getName(); // Dolly 498 | echo $cloned->getCategory(); // Mountain sheep 499 | ``` 500 | 501 | Also you could use the magic method `__clone` to modify the cloning behavior. 502 | 503 | **When to use?** 504 | 505 | When an object is required that is similar to existing object or when the creation would be expensive as compared to cloning. 506 | 507 | 💍 Singleton 508 | ------------ 509 | Real world example 510 | > There can only be one president of a country at a time. The same president has to be brought to action, whenever duty calls. President here is singleton. 511 | 512 | In plain words 513 | > Ensures that only one object of a particular class is ever created. 514 | 515 | Wikipedia says 516 | > In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. 517 | 518 | Singleton pattern is actually considered an anti-pattern and overuse of it should be avoided. It is not necessarily bad and could have some valid use-cases but should be used with caution because it introduces a global state in your application and change to it in one place could affect in the other areas and it could become pretty difficult to debug. The other bad thing about them is it makes your code tightly coupled plus it mocking the singleton could be difficult. 519 | 520 | **Programmatic Example** 521 | 522 | To create a singleton, make the constructor private, disable cloning, disable extension and create a static variable to house the instance 523 | ```php 524 | final class President 525 | { 526 | private static $instance; 527 | 528 | private function __construct() 529 | { 530 | // Hide the constructor 531 | } 532 | 533 | public static function getInstance(): President 534 | { 535 | if (!self::$instance) { 536 | self::$instance = new self(); 537 | } 538 | 539 | return self::$instance; 540 | } 541 | 542 | private function __clone() 543 | { 544 | // Disable cloning 545 | } 546 | 547 | private function __wakeup() 548 | { 549 | // Disable unserialize 550 | } 551 | } 552 | ``` 553 | Then in order to use 554 | ```php 555 | $president1 = President::getInstance(); 556 | $president2 = President::getInstance(); 557 | 558 | var_dump($president1 === $president2); // true 559 | ``` 560 | 561 | Structural Design Patterns 562 | ========================== 563 | In plain words 564 | > Structural patterns are mostly concerned with object composition or in other words how the entities can use each other. Or yet another explanation would be, they help in answering "How to build a software component?" 565 | 566 | Wikipedia says 567 | > In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities. 568 | 569 | * [Adapter](#-adapter) 570 | * [Bridge](#-bridge) 571 | * [Composite](#-composite) 572 | * [Decorator](#-decorator) 573 | * [Facade](#-facade) 574 | * [Flyweight](#-flyweight) 575 | * [Proxy](#-proxy) 576 | 577 | 🔌 Adapter 578 | ------- 579 | Real world example 580 | > Consider that you have some pictures in your memory card and you need to transfer them to your computer. In order to transfer them you need some kind of adapter that is compatible with your computer ports so that you can attach memory card to your computer. In this case card reader is an adapter. 581 | > Another example would be the famous power adapter; a three legged plug can't be connected to a two pronged outlet, it needs to use a power adapter that makes it compatible with the two pronged outlet. 582 | > Yet another example would be a translator translating words spoken by one person to another 583 | 584 | In plain words 585 | > Adapter pattern lets you wrap an otherwise incompatible object in an adapter to make it compatible with another class. 586 | 587 | Wikipedia says 588 | > In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code. 589 | 590 | **Programmatic Example** 591 | 592 | Consider a game where there is a hunter and he hunts lions. 593 | 594 | First we have an interface `Lion` that all types of lions have to implement 595 | 596 | ```php 597 | interface Lion 598 | { 599 | public function roar(); 600 | } 601 | 602 | class AfricanLion implements Lion 603 | { 604 | public function roar() 605 | { 606 | } 607 | } 608 | 609 | class AsianLion implements Lion 610 | { 611 | public function roar() 612 | { 613 | } 614 | } 615 | ``` 616 | And hunter expects any implementation of `Lion` interface to hunt. 617 | ```php 618 | class Hunter 619 | { 620 | public function hunt(Lion $lion) 621 | { 622 | } 623 | } 624 | ``` 625 | 626 | Now let's say we have to add a `WildDog` in our game so that hunter can hunt that also. But we can't do that directly because dog has a different interface. To make it compatible for our hunter, we will have to create an adapter that is compatible 627 | 628 | ```php 629 | // This needs to be added to the game 630 | class WildDog 631 | { 632 | public function bark() 633 | { 634 | } 635 | } 636 | 637 | // Adapter around wild dog to make it compatible with our game 638 | class WildDogAdapter implements Lion 639 | { 640 | protected $dog; 641 | 642 | public function __construct(WildDog $dog) 643 | { 644 | $this->dog = $dog; 645 | } 646 | 647 | public function roar() 648 | { 649 | $this->dog->bark(); 650 | } 651 | } 652 | ``` 653 | And now the `WildDog` can be used in our game using `WildDogAdapter`. 654 | 655 | ```php 656 | $wildDog = new WildDog(); 657 | $wildDogAdapter = new WildDogAdapter($wildDog); 658 | 659 | $hunter = new Hunter(); 660 | $hunter->hunt($wildDogAdapter); 661 | ``` 662 | 663 | 🚡 Bridge 664 | ------ 665 | Real world example 666 | > Consider you have a website with different pages and you are supposed to allow the user to change the theme. What would you do? Create multiple copies of each of the pages for each of the themes or would you just create separate theme and load them based on the user's preferences? Bridge pattern allows you to do the second i.e. 667 | 668 | ![With and without the bridge pattern](https://cloud.githubusercontent.com/assets/11269635/23065293/33b7aea0-f515-11e6-983f-98823c9845ee.png) 669 | 670 | In Plain Words 671 | > Bridge pattern is about preferring composition over inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy. 672 | 673 | Wikipedia says 674 | > The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently" 675 | 676 | **Programmatic Example** 677 | 678 | Translating our WebPage example from above. Here we have the `WebPage` hierarchy 679 | 680 | ```php 681 | interface WebPage 682 | { 683 | public function __construct(Theme $theme); 684 | public function getContent(); 685 | } 686 | 687 | class About implements WebPage 688 | { 689 | protected $theme; 690 | 691 | public function __construct(Theme $theme) 692 | { 693 | $this->theme = $theme; 694 | } 695 | 696 | public function getContent() 697 | { 698 | return "About page in " . $this->theme->getColor(); 699 | } 700 | } 701 | 702 | class Careers implements WebPage 703 | { 704 | protected $theme; 705 | 706 | public function __construct(Theme $theme) 707 | { 708 | $this->theme = $theme; 709 | } 710 | 711 | public function getContent() 712 | { 713 | return "Careers page in " . $this->theme->getColor(); 714 | } 715 | } 716 | ``` 717 | And the separate theme hierarchy 718 | ```php 719 | 720 | interface Theme 721 | { 722 | public function getColor(); 723 | } 724 | 725 | class DarkTheme implements Theme 726 | { 727 | public function getColor() 728 | { 729 | return 'Dark Black'; 730 | } 731 | } 732 | class LightTheme implements Theme 733 | { 734 | public function getColor() 735 | { 736 | return 'Off white'; 737 | } 738 | } 739 | class AquaTheme implements Theme 740 | { 741 | public function getColor() 742 | { 743 | return 'Light blue'; 744 | } 745 | } 746 | ``` 747 | And both the hierarchies 748 | ```php 749 | $darkTheme = new DarkTheme(); 750 | 751 | $about = new About($darkTheme); 752 | $careers = new Careers($darkTheme); 753 | 754 | echo $about->getContent(); // "About page in Dark Black"; 755 | echo $careers->getContent(); // "Careers page in Dark Black"; 756 | ``` 757 | 758 | 🌿 Composite 759 | ----------------- 760 | 761 | Real world example 762 | > Every organization is composed of employees. Each of the employees has the same features i.e. has a salary, has some responsibilities, may or may not report to someone, may or may not have some subordinates etc. 763 | 764 | In plain words 765 | > Composite pattern lets clients treat the individual objects in a uniform manner. 766 | 767 | Wikipedia says 768 | > In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly. 769 | 770 | **Programmatic Example** 771 | 772 | Taking our employees example from above. Here we have different employee types 773 | 774 | ```php 775 | interface Employee 776 | { 777 | public function __construct(string $name, float $salary); 778 | public function getName(): string; 779 | public function setSalary(float $salary); 780 | public function getSalary(): float; 781 | public function getRoles(): array; 782 | } 783 | 784 | class Developer implements Employee 785 | { 786 | protected $salary; 787 | protected $name; 788 | 789 | public function __construct(string $name, float $salary) 790 | { 791 | $this->name = $name; 792 | $this->salary = $salary; 793 | } 794 | 795 | public function getName(): string 796 | { 797 | return $this->name; 798 | } 799 | 800 | public function setSalary(float $salary) 801 | { 802 | $this->salary = $salary; 803 | } 804 | 805 | public function getSalary(): float 806 | { 807 | return $this->salary; 808 | } 809 | 810 | public function getRoles(): array 811 | { 812 | return $this->roles; 813 | } 814 | } 815 | 816 | class Designer implements Employee 817 | { 818 | protected $salary; 819 | protected $name; 820 | 821 | public function __construct(string $name, float $salary) 822 | { 823 | $this->name = $name; 824 | $this->salary = $salary; 825 | } 826 | 827 | public function getName(): string 828 | { 829 | return $this->name; 830 | } 831 | 832 | public function setSalary(float $salary) 833 | { 834 | $this->salary = $salary; 835 | } 836 | 837 | public function getSalary(): float 838 | { 839 | return $this->salary; 840 | } 841 | 842 | public function getRoles(): array 843 | { 844 | return $this->roles; 845 | } 846 | } 847 | ``` 848 | 849 | Then we have an organization which consists of several different types of employees 850 | 851 | ```php 852 | class Organization 853 | { 854 | protected $employees; 855 | 856 | public function addEmployee(Employee $employee) 857 | { 858 | $this->employees[] = $employee; 859 | } 860 | 861 | public function getNetSalaries(): float 862 | { 863 | $netSalary = 0; 864 | 865 | foreach ($this->employees as $employee) { 866 | $netSalary += $employee->getSalary(); 867 | } 868 | 869 | return $netSalary; 870 | } 871 | } 872 | ``` 873 | 874 | And then it can be used as 875 | 876 | ```php 877 | // Prepare the employees 878 | $john = new Developer('John Doe', 12000); 879 | $jane = new Designer('Jane', 10000); 880 | 881 | // Add them to organization 882 | $organization = new Organization(); 883 | $organization->addEmployee($john); 884 | $organization->addEmployee($jane); 885 | 886 | echo "Net salaries: " . $organization->getNetSalaries(); // Net Salaries: 22000 887 | ``` 888 | 889 | ☕ Decorator 890 | ------------- 891 | 892 | Real world example 893 | 894 | > Imagine you run a car service shop offering multiple services. Now how do you calculate the bill to be charged? You pick one service and dynamically keep adding to it the prices for the provided services till you get the final cost. Here each type of service is a decorator. 895 | 896 | In plain words 897 | > Decorator pattern lets you dynamically change the behavior of an object at run time by wrapping them in an object of a decorator class. 898 | 899 | Wikipedia says 900 | > In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern. 901 | 902 | **Programmatic Example** 903 | 904 | Lets take coffee for example. First of all we have a simple coffee implementing the coffee interface 905 | 906 | ```php 907 | interface Coffee 908 | { 909 | public function getCost(); 910 | public function getDescription(); 911 | } 912 | 913 | class SimpleCoffee implements Coffee 914 | { 915 | public function getCost() 916 | { 917 | return 10; 918 | } 919 | 920 | public function getDescription() 921 | { 922 | return 'Simple coffee'; 923 | } 924 | } 925 | ``` 926 | We want to make the code extensible to allow options to modify it if required. Lets make some add-ons (decorators) 927 | ```php 928 | class MilkCoffee implements Coffee 929 | { 930 | protected $coffee; 931 | 932 | public function __construct(Coffee $coffee) 933 | { 934 | $this->coffee = $coffee; 935 | } 936 | 937 | public function getCost() 938 | { 939 | return $this->coffee->getCost() + 2; 940 | } 941 | 942 | public function getDescription() 943 | { 944 | return $this->coffee->getDescription() . ', milk'; 945 | } 946 | } 947 | 948 | class WhipCoffee implements Coffee 949 | { 950 | protected $coffee; 951 | 952 | public function __construct(Coffee $coffee) 953 | { 954 | $this->coffee = $coffee; 955 | } 956 | 957 | public function getCost() 958 | { 959 | return $this->coffee->getCost() + 5; 960 | } 961 | 962 | public function getDescription() 963 | { 964 | return $this->coffee->getDescription() . ', whip'; 965 | } 966 | } 967 | 968 | class VanillaCoffee implements Coffee 969 | { 970 | protected $coffee; 971 | 972 | public function __construct(Coffee $coffee) 973 | { 974 | $this->coffee = $coffee; 975 | } 976 | 977 | public function getCost() 978 | { 979 | return $this->coffee->getCost() + 3; 980 | } 981 | 982 | public function getDescription() 983 | { 984 | return $this->coffee->getDescription() . ', vanilla'; 985 | } 986 | } 987 | ``` 988 | 989 | Lets make a coffee now 990 | 991 | ```php 992 | $someCoffee = new SimpleCoffee(); 993 | echo $someCoffee->getCost(); // 10 994 | echo $someCoffee->getDescription(); // Simple Coffee 995 | 996 | $someCoffee = new MilkCoffee($someCoffee); 997 | echo $someCoffee->getCost(); // 12 998 | echo $someCoffee->getDescription(); // Simple Coffee, milk 999 | 1000 | $someCoffee = new WhipCoffee($someCoffee); 1001 | echo $someCoffee->getCost(); // 17 1002 | echo $someCoffee->getDescription(); // Simple Coffee, milk, whip 1003 | 1004 | $someCoffee = new VanillaCoffee($someCoffee); 1005 | echo $someCoffee->getCost(); // 20 1006 | echo $someCoffee->getDescription(); // Simple Coffee, milk, whip, vanilla 1007 | ``` 1008 | 1009 | 📦 Facade 1010 | ---------------- 1011 | 1012 | Real world example 1013 | > How do you turn on the computer? "Hit the power button" you say! That is what you believe because you are using a simple interface that computer provides on the outside, internally it has to do a lot of stuff to make it happen. This simple interface to the complex subsystem is a facade. 1014 | 1015 | In plain words 1016 | > Facade pattern provides a simplified interface to a complex subsystem. 1017 | 1018 | Wikipedia says 1019 | > A facade is an object that provides a simplified interface to a larger body of code, such as a class library. 1020 | 1021 | **Programmatic Example** 1022 | 1023 | Taking our computer example from above. Here we have the computer class 1024 | 1025 | ```php 1026 | class Computer 1027 | { 1028 | public function getElectricShock() 1029 | { 1030 | echo "Ouch!"; 1031 | } 1032 | 1033 | public function makeSound() 1034 | { 1035 | echo "Beep beep!"; 1036 | } 1037 | 1038 | public function showLoadingScreen() 1039 | { 1040 | echo "Loading.."; 1041 | } 1042 | 1043 | public function bam() 1044 | { 1045 | echo "Ready to be used!"; 1046 | } 1047 | 1048 | public function closeEverything() 1049 | { 1050 | echo "Bup bup bup buzzzz!"; 1051 | } 1052 | 1053 | public function sooth() 1054 | { 1055 | echo "Zzzzz"; 1056 | } 1057 | 1058 | public function pullCurrent() 1059 | { 1060 | echo "Haaah!"; 1061 | } 1062 | } 1063 | ``` 1064 | Here we have the facade 1065 | ```php 1066 | class ComputerFacade 1067 | { 1068 | protected $computer; 1069 | 1070 | public function __construct(Computer $computer) 1071 | { 1072 | $this->computer = $computer; 1073 | } 1074 | 1075 | public function turnOn() 1076 | { 1077 | $this->computer->getElectricShock(); 1078 | $this->computer->makeSound(); 1079 | $this->computer->showLoadingScreen(); 1080 | $this->computer->bam(); 1081 | } 1082 | 1083 | public function turnOff() 1084 | { 1085 | $this->computer->closeEverything(); 1086 | $this->computer->pullCurrent(); 1087 | $this->computer->sooth(); 1088 | } 1089 | } 1090 | ``` 1091 | Now to use the facade 1092 | ```php 1093 | $computer = new ComputerFacade(new Computer()); 1094 | $computer->turnOn(); // Ouch! Beep beep! Loading.. Ready to be used! 1095 | $computer->turnOff(); // Bup bup buzzz! Haah! Zzzzz 1096 | ``` 1097 | 1098 | 🍃 Flyweight 1099 | --------- 1100 | 1101 | Real world example 1102 | > Did you ever have fresh tea from some stall? They often make more than one cup that you demanded and save the rest for any other customer so to save the resources e.g. gas etc. Flyweight pattern is all about that i.e. sharing. 1103 | 1104 | In plain words 1105 | > It is used to minimize memory usage or computational expenses by sharing as much as possible with similar objects. 1106 | 1107 | Wikipedia says 1108 | > In computer programming, flyweight is a software design pattern. A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory. 1109 | 1110 | **Programmatic example** 1111 | 1112 | Translating our tea example from above. First of all we have tea types and tea maker 1113 | 1114 | ```php 1115 | // Anything that will be cached is flyweight. 1116 | // Types of tea here will be flyweights. 1117 | class KarakTea 1118 | { 1119 | } 1120 | 1121 | // Acts as a factory and saves the tea 1122 | class TeaMaker 1123 | { 1124 | protected $availableTea = []; 1125 | 1126 | public function make($preference) 1127 | { 1128 | if (empty($this->availableTea[$preference])) { 1129 | $this->availableTea[$preference] = new KarakTea(); 1130 | } 1131 | 1132 | return $this->availableTea[$preference]; 1133 | } 1134 | } 1135 | ``` 1136 | 1137 | Then we have the `TeaShop` which takes orders and serves them 1138 | 1139 | ```php 1140 | class TeaShop 1141 | { 1142 | protected $orders; 1143 | protected $teaMaker; 1144 | 1145 | public function __construct(TeaMaker $teaMaker) 1146 | { 1147 | $this->teaMaker = $teaMaker; 1148 | } 1149 | 1150 | public function takeOrder(string $teaType, int $table) 1151 | { 1152 | $this->orders[$table] = $this->teaMaker->make($teaType); 1153 | } 1154 | 1155 | public function serve() 1156 | { 1157 | foreach ($this->orders as $table => $tea) { 1158 | echo "Serving tea to table# " . $table; 1159 | } 1160 | } 1161 | } 1162 | ``` 1163 | And it can be used as below 1164 | 1165 | ```php 1166 | $teaMaker = new TeaMaker(); 1167 | $shop = new TeaShop($teaMaker); 1168 | 1169 | $shop->takeOrder('less sugar', 1); 1170 | $shop->takeOrder('more milk', 2); 1171 | $shop->takeOrder('without sugar', 5); 1172 | 1173 | $shop->serve(); 1174 | // Serving tea to table# 1 1175 | // Serving tea to table# 2 1176 | // Serving tea to table# 5 1177 | ``` 1178 | 1179 | 🎱 Proxy 1180 | ------------------- 1181 | Real world example 1182 | > Have you ever used an access card to go through a door? There are multiple options to open that door i.e. it can be opened either using access card or by pressing a button that bypasses the security. The door's main functionality is to open but there is a proxy added on top of it to add some functionality. Let me better explain it using the code example below. 1183 | 1184 | In plain words 1185 | > Using the proxy pattern, a class represents the functionality of another class. 1186 | 1187 | Wikipedia says 1188 | > A proxy, in its most general form, is a class functioning as an interface to something else. A proxy is a wrapper or agent object that is being called by the client to access the real serving object behind the scenes. Use of the proxy can simply be forwarding to the real object, or can provide additional logic. In the proxy extra functionality can be provided, for example caching when operations on the real object are resource intensive, or checking preconditions before operations on the real object are invoked. 1189 | 1190 | **Programmatic Example** 1191 | 1192 | Taking our security door example from above. Firstly we have the door interface and an implementation of door 1193 | 1194 | ```php 1195 | interface Door 1196 | { 1197 | public function open(); 1198 | public function close(); 1199 | } 1200 | 1201 | class LabDoor implements Door 1202 | { 1203 | public function open() 1204 | { 1205 | echo "Opening lab door"; 1206 | } 1207 | 1208 | public function close() 1209 | { 1210 | echo "Closing the lab door"; 1211 | } 1212 | } 1213 | ``` 1214 | Then we have a proxy to secure any doors that we want 1215 | ```php 1216 | class Security 1217 | { 1218 | protected $door; 1219 | 1220 | public function __construct(Door $door) 1221 | { 1222 | $this->door = $door; 1223 | } 1224 | 1225 | public function open($password) 1226 | { 1227 | if ($this->authenticate($password)) { 1228 | $this->door->open(); 1229 | } else { 1230 | echo "Big no! It ain't possible."; 1231 | } 1232 | } 1233 | 1234 | public function authenticate($password) 1235 | { 1236 | return $password === '$ecr@t'; 1237 | } 1238 | 1239 | public function close() 1240 | { 1241 | $this->door->close(); 1242 | } 1243 | } 1244 | ``` 1245 | And here is how it can be used 1246 | ```php 1247 | $door = new Security(new LabDoor()); 1248 | $door->open('invalid'); // Big no! It ain't possible. 1249 | 1250 | $door->open('$ecr@t'); // Opening lab door 1251 | $door->close(); // Closing lab door 1252 | ``` 1253 | Yet another example would be some sort of data-mapper implementation. For example, I recently made an ODM (Object Data Mapper) for MongoDB using this pattern where I wrote a proxy around mongo classes while utilizing the magic method `__call()`. All the method calls were proxied to the original mongo class and result retrieved was returned as it is but in case of `find` or `findOne` data was mapped to the required class objects and the object was returned instead of `Cursor`. 1254 | 1255 | Behavioral Design Patterns 1256 | ========================== 1257 | 1258 | In plain words 1259 | > It is concerned with assignment of responsibilities between the objects. What makes them different from structural patterns is they don't just specify the structure but also outline the patterns for message passing/communication between them. Or in other words, they assist in answering "How to run a behavior in software component?" 1260 | 1261 | Wikipedia says 1262 | > In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication. 1263 | 1264 | * [Chain of Responsibility](#-chain-of-responsibility) 1265 | * [Command](#-command) 1266 | * [Iterator](#-iterator) 1267 | * [Mediator](#-mediator) 1268 | * [Memento](#-memento) 1269 | * [Observer](#-observer) 1270 | * [Visitor](#-visitor) 1271 | * [Strategy](#-strategy) 1272 | * [State](#-state) 1273 | * [Template Method](#-template-method) 1274 | 1275 | 🔗 Chain of Responsibility 1276 | ----------------------- 1277 | 1278 | Real world example 1279 | > For example, you have three payment methods (`A`, `B` and `C`) setup in your account; each having a different amount in it. `A` has 100 USD, `B` has 300 USD and `C` having 1000 USD and the preference for payments is chosen as `A` then `B` then `C`. You try to purchase something that is worth 210 USD. Using Chain of Responsibility, first of all account `A` will be checked if it can make the purchase, if yes purchase will be made and the chain will be broken. If not, request will move forward to account `B` checking for amount if yes chain will be broken otherwise the request will keep forwarding till it finds the suitable handler. Here `A`, `B` and `C` are links of the chain and the whole phenomenon is Chain of Responsibility. 1280 | 1281 | In plain words 1282 | > It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler. 1283 | 1284 | Wikipedia says 1285 | > In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain. 1286 | 1287 | **Programmatic Example** 1288 | 1289 | Translating our account example above. First of all we have a base account having the logic for chaining the accounts together and some accounts 1290 | 1291 | ```php 1292 | abstract class Account 1293 | { 1294 | protected $successor; 1295 | protected $balance; 1296 | 1297 | public function setNext(Account $account) 1298 | { 1299 | $this->successor = $account; 1300 | } 1301 | 1302 | public function pay(float $amountToPay) 1303 | { 1304 | if ($this->canPay($amountToPay)) { 1305 | echo sprintf('Paid %s using %s' . PHP_EOL, $amountToPay, get_called_class()); 1306 | } elseif ($this->successor) { 1307 | echo sprintf('Cannot pay using %s. Proceeding ..' . PHP_EOL, get_called_class()); 1308 | $this->successor->pay($amountToPay); 1309 | } else { 1310 | throw new Exception('None of the accounts have enough balance'); 1311 | } 1312 | } 1313 | 1314 | public function canPay($amount): bool 1315 | { 1316 | return $this->balance >= $amount; 1317 | } 1318 | } 1319 | 1320 | class Bank extends Account 1321 | { 1322 | protected $balance; 1323 | 1324 | public function __construct(float $balance) 1325 | { 1326 | $this->balance = $balance; 1327 | } 1328 | } 1329 | 1330 | class Paypal extends Account 1331 | { 1332 | protected $balance; 1333 | 1334 | public function __construct(float $balance) 1335 | { 1336 | $this->balance = $balance; 1337 | } 1338 | } 1339 | 1340 | class Bitcoin extends Account 1341 | { 1342 | protected $balance; 1343 | 1344 | public function __construct(float $balance) 1345 | { 1346 | $this->balance = $balance; 1347 | } 1348 | } 1349 | ``` 1350 | 1351 | Now let's prepare the chain using the links defined above (i.e. Bank, Paypal, Bitcoin) 1352 | 1353 | ```php 1354 | // Let's prepare a chain like below 1355 | // $bank->$paypal->$bitcoin 1356 | // 1357 | // First priority bank 1358 | // If bank can't pay then paypal 1359 | // If paypal can't pay then bit coin 1360 | 1361 | $bank = new Bank(100); // Bank with balance 100 1362 | $paypal = new Paypal(200); // Paypal with balance 200 1363 | $bitcoin = new Bitcoin(300); // Bitcoin with balance 300 1364 | 1365 | $bank->setNext($paypal); 1366 | $paypal->setNext($bitcoin); 1367 | 1368 | // Let's try to pay using the first priority i.e. bank 1369 | $bank->pay(259); 1370 | 1371 | // Output will be 1372 | // ============== 1373 | // Cannot pay using bank. Proceeding .. 1374 | // Cannot pay using paypal. Proceeding ..: 1375 | // Paid 259 using Bitcoin! 1376 | ``` 1377 | 1378 | 👮 Command 1379 | ------- 1380 | 1381 | Real world example 1382 | > A generic example would be you ordering a food at restaurant. You (i.e. `Client`) ask the waiter (i.e. `Invoker`) to bring some food (i.e. `Command`) and waiter simply forwards the request to Chef (i.e. `Receiver`) who has the knowledge of what and how to cook. 1383 | > Another example would be you (i.e. `Client`) switching on (i.e. `Command`) the television (i.e. `Receiver`) using a remote control (`Invoker`). 1384 | 1385 | In plain words 1386 | > Allows you to encapsulate actions in objects. The key idea behind this pattern is to provide the means to decouple client from receiver. 1387 | 1388 | Wikipedia says 1389 | > In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters. 1390 | 1391 | **Programmatic Example** 1392 | 1393 | First of all we have the receiver that has the implementation of every action that could be performed 1394 | ```php 1395 | // Receiver 1396 | class Bulb 1397 | { 1398 | public function turnOn() 1399 | { 1400 | echo "Bulb has been lit"; 1401 | } 1402 | 1403 | public function turnOff() 1404 | { 1405 | echo "Darkness!"; 1406 | } 1407 | } 1408 | ``` 1409 | then we have an interface that each of the commands are going to implement and then we have a set of commands 1410 | ```php 1411 | interface Command 1412 | { 1413 | public function execute(); 1414 | public function undo(); 1415 | public function redo(); 1416 | } 1417 | 1418 | // Command 1419 | class TurnOn implements Command 1420 | { 1421 | protected $bulb; 1422 | 1423 | public function __construct(Bulb $bulb) 1424 | { 1425 | $this->bulb = $bulb; 1426 | } 1427 | 1428 | public function execute() 1429 | { 1430 | $this->bulb->turnOn(); 1431 | } 1432 | 1433 | public function undo() 1434 | { 1435 | $this->bulb->turnOff(); 1436 | } 1437 | 1438 | public function redo() 1439 | { 1440 | $this->execute(); 1441 | } 1442 | } 1443 | 1444 | class TurnOff implements Command 1445 | { 1446 | protected $bulb; 1447 | 1448 | public function __construct(Bulb $bulb) 1449 | { 1450 | $this->bulb = $bulb; 1451 | } 1452 | 1453 | public function execute() 1454 | { 1455 | $this->bulb->turnOff(); 1456 | } 1457 | 1458 | public function undo() 1459 | { 1460 | $this->bulb->turnOn(); 1461 | } 1462 | 1463 | public function redo() 1464 | { 1465 | $this->execute(); 1466 | } 1467 | } 1468 | ``` 1469 | Then we have an `Invoker` with whom the client will interact to process any commands 1470 | ```php 1471 | // Invoker 1472 | class RemoteControl 1473 | { 1474 | public function submit(Command $command) 1475 | { 1476 | $command->execute(); 1477 | } 1478 | } 1479 | ``` 1480 | Finally let's see how we can use it in our client 1481 | ```php 1482 | $bulb = new Bulb(); 1483 | 1484 | $turnOn = new TurnOn($bulb); 1485 | $turnOff = new TurnOff($bulb); 1486 | 1487 | $remote = new RemoteControl(); 1488 | $remote->submit($turnOn); // Bulb has been lit! 1489 | $remote->submit($turnOff); // Darkness! 1490 | ``` 1491 | 1492 | Command pattern can also be used to implement a transaction based system. Where you keep maintaining the history of commands as soon as you execute them. If the final command is successfully executed, all good otherwise just iterate through the history and keep executing the `undo` on all the executed commands. 1493 | 1494 | ➿ Iterator 1495 | -------- 1496 | 1497 | Real world example 1498 | > An old radio set will be a good example of iterator, where user could start at some channel and then use next or previous buttons to go through the respective channels. Or take an example of MP3 player or a TV set where you could press the next and previous buttons to go through the consecutive channels or in other words they all provide an interface to iterate through the respective channels, songs or radio stations. 1499 | 1500 | In plain words 1501 | > It presents a way to access the elements of an object without exposing the underlying presentation. 1502 | 1503 | Wikipedia says 1504 | > In object-oriented programming, the iterator pattern is a design pattern in which an iterator is used to traverse a container and access the container's elements. The iterator pattern decouples algorithms from containers; in some cases, algorithms are necessarily container-specific and thus cannot be decoupled. 1505 | 1506 | **Programmatic example** 1507 | 1508 | In PHP it is quite easy to implement using SPL (Standard PHP Library). Translating our radio stations example from above. First of all we have `RadioStation` 1509 | 1510 | ```php 1511 | class RadioStation 1512 | { 1513 | protected $frequency; 1514 | 1515 | public function __construct(float $frequency) 1516 | { 1517 | $this->frequency = $frequency; 1518 | } 1519 | 1520 | public function getFrequency(): float 1521 | { 1522 | return $this->frequency; 1523 | } 1524 | } 1525 | ``` 1526 | Then we have our iterator 1527 | 1528 | ```php 1529 | use Countable; 1530 | use Iterator; 1531 | 1532 | class StationList implements Countable, Iterator 1533 | { 1534 | /** @var RadioStation[] $stations */ 1535 | protected $stations = []; 1536 | 1537 | /** @var int $counter */ 1538 | protected $counter; 1539 | 1540 | public function addStation(RadioStation $station) 1541 | { 1542 | $this->stations[] = $station; 1543 | } 1544 | 1545 | public function removeStation(RadioStation $toRemove) 1546 | { 1547 | $toRemoveFrequency = $toRemove->getFrequency(); 1548 | $this->stations = array_filter($this->stations, function (RadioStation $station) use ($toRemoveFrequency) { 1549 | return $station->getFrequency() !== $toRemoveFrequency; 1550 | }); 1551 | } 1552 | 1553 | public function count(): int 1554 | { 1555 | return count($this->stations); 1556 | } 1557 | 1558 | public function current(): RadioStation 1559 | { 1560 | return $this->stations[$this->counter]; 1561 | } 1562 | 1563 | public function key() 1564 | { 1565 | return $this->counter; 1566 | } 1567 | 1568 | public function next() 1569 | { 1570 | $this->counter++; 1571 | } 1572 | 1573 | public function rewind() 1574 | { 1575 | $this->counter = 0; 1576 | } 1577 | 1578 | public function valid(): bool 1579 | { 1580 | return isset($this->stations[$this->counter]); 1581 | } 1582 | } 1583 | ``` 1584 | And then it can be used as 1585 | ```php 1586 | $stationList = new StationList(); 1587 | 1588 | $stationList->addStation(new RadioStation(89)); 1589 | $stationList->addStation(new RadioStation(101)); 1590 | $stationList->addStation(new RadioStation(102)); 1591 | $stationList->addStation(new RadioStation(103.2)); 1592 | 1593 | foreach($stationList as $station) { 1594 | echo $station->getFrequency() . PHP_EOL; 1595 | } 1596 | 1597 | $stationList->removeStation(new RadioStation(89)); // Will remove station 89 1598 | ``` 1599 | 1600 | 👽 Mediator 1601 | ======== 1602 | 1603 | Real world example 1604 | > A general example would be when you talk to someone on your mobile phone, there is a network provider sitting between you and them and your conversation goes through it instead of being directly sent. In this case network provider is mediator. 1605 | 1606 | In plain words 1607 | > Mediator pattern adds a third party object (called mediator) to control the interaction between two objects (called colleagues). It helps reduce the coupling between the classes communicating with each other. Because now they don't need to have the knowledge of each other's implementation. 1608 | 1609 | Wikipedia says 1610 | > In software engineering, the mediator pattern defines an object that encapsulates how a set of objects interact. This pattern is considered to be a behavioral pattern due to the way it can alter the program's running behavior. 1611 | 1612 | **Programmatic Example** 1613 | 1614 | Here is the simplest example of a chat room (i.e. mediator) with users (i.e. colleagues) sending messages to each other. 1615 | 1616 | First of all, we have the mediator i.e. the chat room 1617 | 1618 | ```php 1619 | interface ChatRoomMediator 1620 | { 1621 | public function showMessage(User $user, string $message); 1622 | } 1623 | 1624 | // Mediator 1625 | class ChatRoom implements ChatRoomMediator 1626 | { 1627 | public function showMessage(User $user, string $message) 1628 | { 1629 | $time = date('M d, y H:i'); 1630 | $sender = $user->getName(); 1631 | 1632 | echo $time . '[' . $sender . ']:' . $message; 1633 | } 1634 | } 1635 | ``` 1636 | 1637 | Then we have our users i.e. colleagues 1638 | ```php 1639 | class User { 1640 | protected $name; 1641 | protected $chatMediator; 1642 | 1643 | public function __construct(string $name, ChatRoomMediator $chatMediator) { 1644 | $this->name = $name; 1645 | $this->chatMediator = $chatMediator; 1646 | } 1647 | 1648 | public function getName() { 1649 | return $this->name; 1650 | } 1651 | 1652 | public function send($message) { 1653 | $this->chatMediator->showMessage($this, $message); 1654 | } 1655 | } 1656 | ``` 1657 | And the usage 1658 | ```php 1659 | $mediator = new ChatRoom(); 1660 | 1661 | $john = new User('John Doe', $mediator); 1662 | $jane = new User('Jane Doe', $mediator); 1663 | 1664 | $john->send('Hi there!'); 1665 | $jane->send('Hey!'); 1666 | 1667 | // Output will be 1668 | // Feb 14, 10:58 [John]: Hi there! 1669 | // Feb 14, 10:58 [Jane]: Hey! 1670 | ``` 1671 | 1672 | 💾 Memento 1673 | ------- 1674 | Real world example 1675 | > Take the example of calculator (i.e. originator), where whenever you perform some calculation the last calculation is saved in memory (i.e. memento) so that you can get back to it and maybe get it restored using some action buttons (i.e. caretaker). 1676 | 1677 | In plain words 1678 | > Memento pattern is about capturing and storing the current state of an object in a manner that it can be restored later on in a smooth manner. 1679 | 1680 | Wikipedia says 1681 | > The memento pattern is a software design pattern that provides the ability to restore an object to its previous state (undo via rollback). 1682 | 1683 | Usually useful when you need to provide some sort of undo functionality. 1684 | 1685 | **Programmatic Example** 1686 | 1687 | Lets take an example of text editor which keeps saving the state from time to time and that you can restore if you want. 1688 | 1689 | First of all we have our memento object that will be able to hold the editor state 1690 | 1691 | ```php 1692 | class EditorMemento 1693 | { 1694 | protected $content; 1695 | 1696 | public function __construct(string $content) 1697 | { 1698 | $this->content = $content; 1699 | } 1700 | 1701 | public function getContent() 1702 | { 1703 | return $this->content; 1704 | } 1705 | } 1706 | ``` 1707 | 1708 | Then we have our editor i.e. originator that is going to use memento object 1709 | 1710 | ```php 1711 | class Editor 1712 | { 1713 | protected $content = ''; 1714 | 1715 | public function type(string $words) 1716 | { 1717 | $this->content = $this->content . ' ' . $words; 1718 | } 1719 | 1720 | public function getContent() 1721 | { 1722 | return $this->content; 1723 | } 1724 | 1725 | public function save() 1726 | { 1727 | return new EditorMemento($this->content); 1728 | } 1729 | 1730 | public function restore(EditorMemento $memento) 1731 | { 1732 | $this->content = $memento->getContent(); 1733 | } 1734 | } 1735 | ``` 1736 | 1737 | And then it can be used as 1738 | 1739 | ```php 1740 | $editor = new Editor(); 1741 | 1742 | // Type some stuff 1743 | $editor->type('This is the first sentence.'); 1744 | $editor->type('This is second.'); 1745 | 1746 | // Save the state to restore to : This is the first sentence. This is second. 1747 | $saved = $editor->save(); 1748 | 1749 | // Type some more 1750 | $editor->type('And this is third.'); 1751 | 1752 | // Output: Content before Saving 1753 | echo $editor->getContent(); // This is the first sentence. This is second. And this is third. 1754 | 1755 | // Restoring to last saved state 1756 | $editor->restore($saved); 1757 | 1758 | $editor->getContent(); // This is the first sentence. This is second. 1759 | ``` 1760 | 1761 | 😎 Observer 1762 | -------- 1763 | Real world example 1764 | > A good example would be the job seekers where they subscribe to some job posting site and they are notified whenever there is a matching job opportunity. 1765 | 1766 | In plain words 1767 | > Defines a dependency between objects so that whenever an object changes its state, all its dependents are notified. 1768 | 1769 | Wikipedia says 1770 | > The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. 1771 | 1772 | **Programmatic example** 1773 | 1774 | Translating our example from above. First of all we have job seekers that need to be notified for a job posting 1775 | ```php 1776 | class JobPost 1777 | { 1778 | protected $title; 1779 | 1780 | public function __construct(string $title) 1781 | { 1782 | $this->title = $title; 1783 | } 1784 | 1785 | public function getTitle() 1786 | { 1787 | return $this->title; 1788 | } 1789 | } 1790 | 1791 | class JobSeeker implements Observer 1792 | { 1793 | protected $name; 1794 | 1795 | public function __construct(string $name) 1796 | { 1797 | $this->name = $name; 1798 | } 1799 | 1800 | public function onJobPosted(JobPost $job) 1801 | { 1802 | // Do something with the job posting 1803 | echo 'Hi ' . $this->name . '! New job posted: '. $job->getTitle(); 1804 | } 1805 | } 1806 | ``` 1807 | Then we have our job postings to which the job seekers will subscribe 1808 | ```php 1809 | class JobPostings implements Observable 1810 | { 1811 | protected $observers = []; 1812 | 1813 | protected function notify(JobPost $jobPosting) 1814 | { 1815 | foreach ($this->observers as $observer) { 1816 | $observer->onJobPosted($jobPosting); 1817 | } 1818 | } 1819 | 1820 | public function attach(Observer $observer) 1821 | { 1822 | $this->observers[] = $observer; 1823 | } 1824 | 1825 | public function addJob(JobPost $jobPosting) 1826 | { 1827 | $this->notify($jobPosting); 1828 | } 1829 | } 1830 | ``` 1831 | Then it can be used as 1832 | ```php 1833 | // Create subscribers 1834 | $johnDoe = new JobSeeker('John Doe'); 1835 | $janeDoe = new JobSeeker('Jane Doe'); 1836 | 1837 | // Create publisher and attach subscribers 1838 | $jobPostings = new JobPostings(); 1839 | $jobPostings->attach($johnDoe); 1840 | $jobPostings->attach($janeDoe); 1841 | 1842 | // Add a new job and see if subscribers get notified 1843 | $jobPostings->addJob(new JobPost('Software Engineer')); 1844 | 1845 | // Output 1846 | // Hi John Doe! New job posted: Software Engineer 1847 | // Hi Jane Doe! New job posted: Software Engineer 1848 | ``` 1849 | 1850 | 🏃 Visitor 1851 | ------- 1852 | Real world example 1853 | > Consider someone visiting Dubai. They just need a way (i.e. visa) to enter Dubai. After arrival, they can come and visit any place in Dubai on their own without having to ask for permission or to do some leg work in order to visit any place here; just let them know of a place and they can visit it. Visitor pattern lets you do just that, it helps you add places to visit so that they can visit as much as they can without having to do any legwork. 1854 | 1855 | In plain words 1856 | > Visitor pattern lets you add further operations to objects without having to modify them. 1857 | 1858 | Wikipedia says 1859 | > In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures. It is one way to follow the open/closed principle. 1860 | 1861 | **Programmatic example** 1862 | 1863 | Let's take an example of a zoo simulation where we have several different kinds of animals and we have to make them Sound. Let's translate this using visitor pattern 1864 | 1865 | ```php 1866 | // Visitee 1867 | interface Animal 1868 | { 1869 | public function accept(AnimalOperation $operation); 1870 | } 1871 | 1872 | // Visitor 1873 | interface AnimalOperation 1874 | { 1875 | public function visitMonkey(Monkey $monkey); 1876 | public function visitLion(Lion $lion); 1877 | public function visitDolphin(Dolphin $dolphin); 1878 | } 1879 | ``` 1880 | Then we have our implementations for the animals 1881 | ```php 1882 | class Monkey implements Animal 1883 | { 1884 | public function shout() 1885 | { 1886 | echo 'Ooh oo aa aa!'; 1887 | } 1888 | 1889 | public function accept(AnimalOperation $operation) 1890 | { 1891 | $operation->visitMonkey($this); 1892 | } 1893 | } 1894 | 1895 | class Lion implements Animal 1896 | { 1897 | public function roar() 1898 | { 1899 | echo 'Roaaar!'; 1900 | } 1901 | 1902 | public function accept(AnimalOperation $operation) 1903 | { 1904 | $operation->visitLion($this); 1905 | } 1906 | } 1907 | 1908 | class Dolphin implements Animal 1909 | { 1910 | public function speak() 1911 | { 1912 | echo 'Tuut tuttu tuutt!'; 1913 | } 1914 | 1915 | public function accept(AnimalOperation $operation) 1916 | { 1917 | $operation->visitDolphin($this); 1918 | } 1919 | } 1920 | ``` 1921 | Let's implement our visitor 1922 | ```php 1923 | class Speak implements AnimalOperation 1924 | { 1925 | public function visitMonkey(Monkey $monkey) 1926 | { 1927 | $monkey->shout(); 1928 | } 1929 | 1930 | public function visitLion(Lion $lion) 1931 | { 1932 | $lion->roar(); 1933 | } 1934 | 1935 | public function visitDolphin(Dolphin $dolphin) 1936 | { 1937 | $dolphin->speak(); 1938 | } 1939 | } 1940 | ``` 1941 | 1942 | And then it can be used as 1943 | ```php 1944 | $monkey = new Monkey(); 1945 | $lion = new Lion(); 1946 | $dolphin = new Dolphin(); 1947 | 1948 | $speak = new Speak(); 1949 | 1950 | $monkey->accept($speak); // Ooh oo aa aa! 1951 | $lion->accept($speak); // Roaaar! 1952 | $dolphin->accept($speak); // Tuut tutt tuutt! 1953 | ``` 1954 | We could have done this simply by having a inheritance hierarchy for the animals but then we would have to modify the animals whenever we would have to add new actions to animals. But now we will not have to change them. For example, let's say we are asked to add the jump behavior to the animals, we can simply add that by creating a new visitor i.e. 1955 | 1956 | ```php 1957 | class Jump implements AnimalOperation 1958 | { 1959 | public function visitMonkey(Monkey $monkey) 1960 | { 1961 | echo 'Jumped 20 feet high! on to the tree!'; 1962 | } 1963 | 1964 | public function visitLion(Lion $lion) 1965 | { 1966 | echo 'Jumped 7 feet! Back on the ground!'; 1967 | } 1968 | 1969 | public function visitDolphin(Dolphin $dolphin) 1970 | { 1971 | echo 'Walked on water a little and disappeared'; 1972 | } 1973 | } 1974 | ``` 1975 | And for the usage 1976 | ```php 1977 | $jump = new Jump(); 1978 | 1979 | $monkey->accept($speak); // Ooh oo aa aa! 1980 | $monkey->accept($jump); // Jumped 20 feet high! on to the tree! 1981 | 1982 | $lion->accept($speak); // Roaaar! 1983 | $lion->accept($jump); // Jumped 7 feet! Back on the ground! 1984 | 1985 | $dolphin->accept($speak); // Tuut tutt tuutt! 1986 | $dolphin->accept($jump); // Walked on water a little and disappeared 1987 | ``` 1988 | 1989 | 💡 Strategy 1990 | -------- 1991 | 1992 | Real world example 1993 | > Consider the example of sorting, we implemented bubble sort but the data started to grow and bubble sort started getting very slow. In order to tackle this we implemented Quick sort. But now although the quick sort algorithm was doing better for large datasets, it was very slow for smaller datasets. In order to handle this we implemented a strategy where for small datasets, bubble sort will be used and for larger, quick sort. 1994 | 1995 | In plain words 1996 | > Strategy pattern allows you to switch the algorithm or strategy based upon the situation. 1997 | 1998 | Wikipedia says 1999 | > In computer programming, the strategy pattern (also known as the policy pattern) is a behavioural software design pattern that enables an algorithm's behavior to be selected at runtime. 2000 | 2001 | **Programmatic example** 2002 | 2003 | Translating our example from above. First of all we have our strategy interface and different strategy implementations 2004 | 2005 | ```php 2006 | interface SortStrategy 2007 | { 2008 | public function sort(array $dataset): array; 2009 | } 2010 | 2011 | class BubbleSortStrategy implements SortStrategy 2012 | { 2013 | public function sort(array $dataset): array 2014 | { 2015 | echo "Sorting using bubble sort"; 2016 | 2017 | // Do sorting 2018 | return $dataset; 2019 | } 2020 | } 2021 | 2022 | class QuickSortStrategy implements SortStrategy 2023 | { 2024 | public function sort(array $dataset): array 2025 | { 2026 | echo "Sorting using quick sort"; 2027 | 2028 | // Do sorting 2029 | return $dataset; 2030 | } 2031 | } 2032 | ``` 2033 | 2034 | And then we have our client that is going to use any strategy 2035 | ```php 2036 | class Sorter 2037 | { 2038 | protected $sorter; 2039 | 2040 | public function __construct(SortStrategy $sorter) 2041 | { 2042 | $this->sorter = $sorter; 2043 | } 2044 | 2045 | public function sort(array $dataset): array 2046 | { 2047 | return $this->sorter->sort($dataset); 2048 | } 2049 | } 2050 | ``` 2051 | And it can be used as 2052 | ```php 2053 | $dataset = [1, 5, 4, 3, 2, 8]; 2054 | 2055 | $sorter = new Sorter(new BubbleSortStrategy()); 2056 | $sorter->sort($dataset); // Output : Sorting using bubble sort 2057 | 2058 | $sorter = new Sorter(new QuickSortStrategy()); 2059 | $sorter->sort($dataset); // Output : Sorting using quick sort 2060 | ``` 2061 | 2062 | 💢 State 2063 | ----- 2064 | Real world example 2065 | > Imagine you are using some drawing application, you choose the paint brush to draw. Now the brush changes its behavior based on the selected color i.e. if you have chosen red color it will draw in red, if blue then it will be in blue etc. 2066 | 2067 | In plain words 2068 | > It lets you change the behavior of a class when the state changes. 2069 | 2070 | Wikipedia says 2071 | > The state pattern is a behavioral software design pattern that implements a state machine in an object-oriented way. With the state pattern, a state machine is implemented by implementing each individual state as a derived class of the state pattern interface, and implementing state transitions by invoking methods defined by the pattern's superclass. 2072 | > The state pattern can be interpreted as a strategy pattern which is able to switch the current strategy through invocations of methods defined in the pattern's interface. 2073 | 2074 | **Programmatic example** 2075 | 2076 | Let's take an example of text editor, it lets you change the state of text that is typed i.e. if you have selected bold, it starts writing in bold, if italic then in italics etc. 2077 | 2078 | First of all we have our state interface and some state implementations 2079 | 2080 | ```php 2081 | interface WritingState 2082 | { 2083 | public function write(string $words); 2084 | } 2085 | 2086 | class UpperCase implements WritingState 2087 | { 2088 | public function write(string $words) 2089 | { 2090 | echo strtoupper($words); 2091 | } 2092 | } 2093 | 2094 | class LowerCase implements WritingState 2095 | { 2096 | public function write(string $words) 2097 | { 2098 | echo strtolower($words); 2099 | } 2100 | } 2101 | 2102 | class Default implements WritingState 2103 | { 2104 | public function write(string $words) 2105 | { 2106 | echo $words; 2107 | } 2108 | } 2109 | ``` 2110 | Then we have our editor 2111 | ```php 2112 | class TextEditor 2113 | { 2114 | protected $state; 2115 | 2116 | public function __construct(WritingState $state) 2117 | { 2118 | $this->state = $state; 2119 | } 2120 | 2121 | public function setState(WritingState $state) 2122 | { 2123 | $this->state = $state; 2124 | } 2125 | 2126 | public function type(string $words) 2127 | { 2128 | $this->state->write($words); 2129 | } 2130 | } 2131 | ``` 2132 | And then it can be used as 2133 | ```php 2134 | $editor = new TextEditor(new Default()); 2135 | 2136 | $editor->type('First line'); 2137 | 2138 | $editor->setState(new UpperCase()); 2139 | 2140 | $editor->type('Second line'); 2141 | $editor->type('Third line'); 2142 | 2143 | $editor->setState(new LowerCase()); 2144 | 2145 | $editor->type('Fourth line'); 2146 | $editor->type('Fifth line'); 2147 | 2148 | // Output: 2149 | // First line 2150 | // SECOND LINE 2151 | // THIRD LINE 2152 | // fourth line 2153 | // fifth line 2154 | ``` 2155 | 2156 | 📒 Template Method 2157 | --------------- 2158 | 2159 | Real world example 2160 | > Suppose we are getting some house built. The steps for building might look like 2161 | > - Prepare the base of house 2162 | > - Build the walls 2163 | > - Add roof 2164 | > - Add other floors 2165 | 2166 | > The order of these steps could never be changed i.e. you can't build the roof before building the walls etc but each of the steps could be modified for example walls can be made of wood or polyester or stone. 2167 | 2168 | In plain words 2169 | > Template method defines the skeleton of how a certain algorithm could be performed, but defers the implementation of those steps to the children classes. 2170 | 2171 | Wikipedia says 2172 | > In software engineering, the template method pattern is a behavioral design pattern that defines the program skeleton of an algorithm in an operation, deferring some steps to subclasses. It lets one redefine certain steps of an algorithm without changing the algorithm's structure. 2173 | 2174 | **Programmatic Example** 2175 | 2176 | Imagine we have a build tool that helps us test, lint, build, generate build reports (i.e. code coverage reports, linting report etc) and deploy our app on the test server. 2177 | 2178 | First of all we have our base class that specifies the skeleton for the build algorithm 2179 | ```php 2180 | abstract class Builder 2181 | { 2182 | 2183 | // Template method 2184 | final public function build() 2185 | { 2186 | $this->test(); 2187 | $this->lint(); 2188 | $this->assemble(); 2189 | $this->deploy(); 2190 | } 2191 | 2192 | abstract public function test(); 2193 | abstract public function lint(); 2194 | abstract public function assemble(); 2195 | abstract public function deploy(); 2196 | } 2197 | ``` 2198 | 2199 | Then we can have our implementations 2200 | 2201 | ```php 2202 | class AndroidBuilder extends Builder 2203 | { 2204 | public function test() 2205 | { 2206 | echo 'Running android tests'; 2207 | } 2208 | 2209 | public function lint() 2210 | { 2211 | echo 'Linting the android code'; 2212 | } 2213 | 2214 | public function assemble() 2215 | { 2216 | echo 'Assembling the android build'; 2217 | } 2218 | 2219 | public function deploy() 2220 | { 2221 | echo 'Deploying android build to server'; 2222 | } 2223 | } 2224 | 2225 | class IosBuilder extends Builder 2226 | { 2227 | public function test() 2228 | { 2229 | echo 'Running ios tests'; 2230 | } 2231 | 2232 | public function lint() 2233 | { 2234 | echo 'Linting the ios code'; 2235 | } 2236 | 2237 | public function assemble() 2238 | { 2239 | echo 'Assembling the ios build'; 2240 | } 2241 | 2242 | public function deploy() 2243 | { 2244 | echo 'Deploying ios build to server'; 2245 | } 2246 | } 2247 | ``` 2248 | And then it can be used as 2249 | 2250 | ```php 2251 | $androidBuilder = new AndroidBuilder(); 2252 | $androidBuilder->build(); 2253 | 2254 | // Output: 2255 | // Running android tests 2256 | // Linting the android code 2257 | // Assembling the android build 2258 | // Deploying android build to server 2259 | 2260 | $iosBuilder = new IosBuilder(); 2261 | $iosBuilder->build(); 2262 | 2263 | // Output: 2264 | // Running ios tests 2265 | // Linting the ios code 2266 | // Assembling the ios build 2267 | // Deploying ios build to server 2268 | ``` 2269 | 2270 | ## 🚦 Wrap Up Folks 2271 | 2272 | And that about wraps it up. I will continue to improve this, so you might want to watch/star this repository to revisit. Also, I have plans on writing the same about the architectural patterns, stay tuned for it. 2273 | 2274 | ## 👬 Contribution 2275 | 2276 | - Report issues 2277 | - Open pull request with improvements 2278 | - Spread the word 2279 | - Reach out to me directly at kamranahmed.se@gmail.com or on twitter [@kamranahmedse](http://twitter.com/kamranahmedse) 2280 | 2281 | ## License 2282 | MIT © [Kamran Ahmed](http://kamranahmed.info) 2283 | --------------------------------------------------------------------------------