diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..cc5c56e7
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+# These are supported funding model platforms
+
+github: [kamranahmedse]
diff --git a/.github/banner.svg b/.github/banner.svg
new file mode 100644
index 00000000..8deae71a
--- /dev/null
+++ b/.github/banner.svg
@@ -0,0 +1,5 @@
+
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index d5480d44..00000000
--- a/LICENSE
+++ /dev/null
@@ -1,7 +0,0 @@
-Copyright 2017 Kamran Ahmed
-
-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:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-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.
diff --git a/README.md b/readme.md
similarity index 67%
rename from README.md
rename to readme.md
index 07031cba..bacfcaa2 100644
--- a/README.md
+++ b/readme.md
@@ -1,22 +1,44 @@
+
-
+
***
+
๐ Ultra-simplified explanation to design patterns! ๐
-A topic that can easily make anyone's mind wobble. Here I try to make them stick in to your (and maybe mine) mind by explaining them in the simplest way possible.
+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.
+
***
-๐ Introduction
+Check out my [other project](http://roadmap.sh) and say "hi" on [Twitter](https://twitter.com/kamrify).
+
+
+
+|[Creational Design Patterns](#creational-design-patterns)|[Structural Design Patterns](#structural-design-patterns)|[Behavioral Design Patterns](#behavioral-design-patterns)|
+|:-|:-|:-|
+|[Simple Factory](#-simple-factory)|[Adapter](#-adapter)|[Chain of Responsibility](#-chain-of-responsibility)|
+|[Factory Method](#-factory-method)|[Bridge](#-bridge)|[Command](#-command)|
+|[Abstract Factory](#-abstract-factory)|[Composite](#-composite)|[Iterator](#-iterator)|
+|[Builder](#-builder)|[Decorator](#-decorator)|[Mediator](#-mediator)|
+|[Prototype](#-prototype)|[Facade](#-facade)|[Memento](#-memento)|
+|[Singleton](#-singleton)|[Flyweight](#-flyweight)|[Observer](#-observer)|
+||[Proxy](#-proxy)|[Visitor](#-visitor)|
+|||[Strategy](#-strategy)|
+|||[State](#-state)|
+|||[Template Method](#-template-method)|
+
+
+
+Introduction
=================
-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.
+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.
-> Design patterns solutions to recurring problems; guidelines on how to tackle certain problems
+> Design patterns are solutions to recurring problems; guidelines on how to tackle certain problems
Wikipedia describes them as
@@ -25,9 +47,12 @@ Wikipedia describes them as
โ ๏ธ Be Careful
-----------------
- Design patterns are not a silver bullet to all your problems.
-- 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.
+- 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.
- 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.
+> Also note that the code samples below are in PHP-7, however this shouldn't stop you because the concepts are same anyways.
+
Types of Design Patterns
-----------------
@@ -35,7 +60,6 @@ Types of Design Patterns
* [Structural](#structural-design-patterns)
* [Behavioral](#behavioral-design-patterns)
-
Creational Design Patterns
==========================
@@ -44,18 +68,18 @@ In plain words
Wikipedia says
> 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.
-
+
* [Simple Factory](#-simple-factory)
* [Factory Method](#-factory-method)
* [Abstract Factory](#-abstract-factory)
* [Builder](#-builder)
* [Prototype](#-prototype)
* [Singleton](#-singleton)
-
+
๐ Simple Factory
--------------
Real world example
-> 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.
+> Consider, you are building a house and you need doors. You can either put on your carpenter clothes, bring some wood, glue, nails and all the tools required to build the door and start building it in your house or you can simply call the factory and get the built door delivered to you so that you don't need to learn anything about the door making or to deal with the mess that comes with making it.
In plain words
> Simple factory simply generates an instance for client without exposing any instantiation logic to the client
@@ -67,77 +91,94 @@ Wikipedia says
First of all we have a door interface and the implementation
```php
-interface Door {
- public function getWidth() : float;
- public function getHeight() : float;
+interface Door
+{
+ public function getWidth(): float;
+ public function getHeight(): float;
}
-class WoodenDoor implements Door {
+class WoodenDoor implements Door
+{
protected $width;
protected $height;
- public function __construct(float $width, float $height) {
+ public function __construct(float $width, float $height)
+ {
$this->width = $width;
$this->height = $height;
}
-
- public function getWidth() : float {
+
+ public function getWidth(): float
+ {
return $this->width;
}
-
- public function getHeight() : float {
+
+ public function getHeight(): float
+ {
return $this->height;
}
}
-````
+```
Then we have our door factory that makes the door and returns it
```php
-class DoorFactory {
- public static function makeDoor($width, $height) : Door {
- return new WoodenDoor($width, $height);
- }
+class DoorFactory
+{
+ public static function makeDoor($width, $height): Door
+ {
+ return new WoodenDoor($width, $height);
+ }
}
```
And then it can be used as
```php
+// Make me a door of 100x200
$door = DoorFactory::makeDoor(100, 200);
+
echo 'Width: ' . $door->getWidth();
echo 'Height: ' . $door->getHeight();
+
+// Make me a door of 50x100
+$door2 = DoorFactory::makeDoor(50, 100);
```
**When to Use?**
-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.
+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.
๐ญ Factory Method
--------------
Real world example
-> 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.
+> 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.
In plain words
-> It provides a way to delegate the instantiation logic to child classes.
+> It provides a way to delegate the instantiation logic to child classes.
Wikipedia says
> 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.
-
+
**Programmatic Example**
-
+
Taking our hiring manager example above. First of all we have an interviewer interface and some implementations for it
```php
-interface Interviewer {
+interface Interviewer
+{
public function askQuestions();
}
-class Developer implements Interviewer {
- public function askQuestions() {
+class Developer implements Interviewer
+{
+ public function askQuestions()
+ {
echo 'Asking about design patterns!';
}
}
-class CommunityExecutive implements Interviewer {
- public function askQuestions() {
+class CommunityExecutive implements Interviewer
+{
+ public function askQuestions()
+ {
echo 'Asking about community building';
}
}
@@ -146,27 +187,34 @@ class CommunityExecutive implements Interviewer {
Now let us create our `HiringManager`
```php
- class HiringManager {
-
+abstract class HiringManager
+{
+
// Factory method
- abstract public function makeInterviewer() : Interviewer;
-
- public function takeInterview() {
+ abstract protected function makeInterviewer(): Interviewer;
+
+ public function takeInterview()
+ {
$interviewer = $this->makeInterviewer();
$interviewer->askQuestions();
}
- }
- ```
+}
+
+```
Now any child can extend it and provide the required interviewer
```php
-class DevelopmentManager extends HiringManager {
- public function makeInterviewer() : Interviewer {
+class DevelopmentManager extends HiringManager
+{
+ protected function makeInterviewer(): Interviewer
+ {
return new Developer();
}
}
-class MarketingManager extends HiringManager {
- public function makeInterviewer() : Interviewer {
+class MarketingManager extends HiringManager
+{
+ protected function makeInterviewer(): Interviewer
+ {
return new CommunityExecutive();
}
}
@@ -192,8 +240,8 @@ Real world example
> 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.
In plain words
-> A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes.
-
+> A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes.
+
Wikipedia says
> The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes
@@ -202,18 +250,23 @@ Wikipedia says
Translating the door example above. First of all we have our `Door` interface and some implementation for it
```php
-interface Door {
+interface Door
+{
public function getDescription();
}
-class WoodenDoor implements Door {
- public function getDescription() {
+class WoodenDoor implements Door
+{
+ public function getDescription()
+ {
echo 'I am a wooden door';
}
}
-class IronDoor implements Door {
- public function getDescription() {
+class IronDoor implements Door
+{
+ public function getDescription()
+ {
echo 'I am an iron door';
}
}
@@ -221,48 +274,60 @@ class IronDoor implements Door {
Then we have some fitting experts for each door type
```php
-interface DoorFittingExpert {
+interface DoorFittingExpert
+{
public function getDescription();
}
-class Welder implements DoorFittingExpert {
- public function getDescription() {
+class Welder implements DoorFittingExpert
+{
+ public function getDescription()
+ {
echo 'I can only fit iron doors';
}
}
-class Carpenter implements DoorFittingExpert {
- public function getDescription() {
+class Carpenter implements DoorFittingExpert
+{
+ public function getDescription()
+ {
echo 'I can only fit wooden doors';
}
}
```
-Now we have our abstract factory that would let us make family of related objects i.e. wooden door would create a wooden door fitting expert and iron door would create an iron door fitting expert
+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
```php
-interface DoorFactory {
- public function makeDoor() : Door;
- public function makeFittingExpert() : DoorFittingExpert;
+interface DoorFactory
+{
+ public function makeDoor(): Door;
+ public function makeFittingExpert(): DoorFittingExpert;
}
// Wooden factory to return carpenter and wooden door
-class WoodenDoorFactory implements DoorFactory {
- public function makeDoor() : Door {
+class WoodenDoorFactory implements DoorFactory
+{
+ public function makeDoor(): Door
+ {
return new WoodenDoor();
}
- public function makeFittingExpert() : DoorFittingExpert{
+ public function makeFittingExpert(): DoorFittingExpert
+ {
return new Carpenter();
}
}
// Iron door factory to get iron door and the relevant fitting expert
-class IronDoorFactory implements DoorFactory {
- public function makeDoor() : Door {
+class IronDoorFactory implements DoorFactory
+{
+ public function makeDoor(): Door
+ {
return new IronDoor();
}
- public function makeFittingExpert() : DoorFittingExpert{
+ public function makeFittingExpert(): DoorFittingExpert
+ {
return new Welder();
}
}
@@ -293,21 +358,22 @@ As you can see the wooden door factory has encapsulated the `carpenter` and the
When there are interrelated dependencies with not-that-simple creation logic involved
-๐ท Builder Pattern
+๐ท Builder
--------------------------------------------
Real world example
> 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.
In plain words
> 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.
-
+
Wikipedia says
> The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor anti-pattern.
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:
-
+
```php
-public function __construct($size, $cheese = true, $pepperoni = true, $tomato = false, $lettuce = true) {
+public function __construct($size, $cheese = true, $pepperoni = true, $tomato = false, $lettuce = true)
+{
}
```
@@ -315,39 +381,73 @@ As you can see; the number of constructor parameters can quickly get out of hand
**Programmatic Example**
-The sane alternative is to use the builder pattern.
+The sane alternative is to use the builder pattern. First of all we have our burger that we want to make
```php
-class BurgerBuilder {
+class Burger
+{
protected $size;
- protected $pepperoni = true;
- protected $cheeze = true;
- protected $lettuce = true;
+ protected $cheese = false;
+ protected $pepperoni = false;
+ protected $lettuce = false;
protected $tomato = false;
- public function __construct(int $size) {
+ public function __construct(BurgerBuilder $builder)
+ {
+ $this->size = $builder->size;
+ $this->cheese = $builder->cheese;
+ $this->pepperoni = $builder->pepperoni;
+ $this->lettuce = $builder->lettuce;
+ $this->tomato = $builder->tomato;
+ }
+}
+```
+
+And then we have the builder
+
+```php
+class BurgerBuilder
+{
+ public $size;
+
+ public $cheese = false;
+ public $pepperoni = false;
+ public $lettuce = false;
+ public $tomato = false;
+
+ public function __construct(int $size)
+ {
$this->size = $size;
}
-
- public function addPepperoni() {
+
+ public function addPepperoni()
+ {
$this->pepperoni = true;
return $this;
}
-
- public function addLettuce() {
+
+ public function addLettuce()
+ {
$this->lettuce = true;
return $this;
}
-
- public function addTomato() {
+
+ public function addCheese()
+ {
+ $this->cheese = true;
+ return $this;
+ }
+
+ public function addTomato()
+ {
$this->tomato = true;
return $this;
}
-
- public function build() : Burger {
- // creational logic
- return $burger;
+
+ public function build(): Burger
+ {
+ return new Burger($this);
}
}
```
@@ -355,9 +455,9 @@ And then it can be used as:
```php
$burger = (new BurgerBuilder(14))
- ->addPepperoni();
- ->addLettuce();
- ->addTomato();
+ ->addPepperoni()
+ ->addLettuce()
+ ->addTomato()
->build();
```
@@ -381,30 +481,36 @@ In short, it allows you to create a copy of an existing object and modify it to
**Programmatic Example**
In PHP, it can be easily done using `clone`
-
+
```php
-class Sheep {
+class Sheep
+{
protected $name;
protected $category;
- public function __construct(string $name, string $category = 'Mountain Sheep') {
+ public function __construct(string $name, string $category = 'Mountain Sheep')
+ {
$this->name = $name;
$this->category = $category;
}
-
- public function setName(string $name) {
+
+ public function setName(string $name)
+ {
$this->name = $name;
}
- public function getName() {
+ public function getName()
+ {
return $this->name;
}
- public function setCategory(string $category) {
+ public function setCategory(string $category)
+ {
$this->category = $category;
}
- public function getCategory() {
+ public function getCategory()
+ {
return $this->category;
}
}
@@ -434,36 +540,44 @@ Real world example
> 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.
In plain words
-> Ensures that only one object of a particular class is every created.
+> Ensures that only one object of a particular class is ever created.
Wikipedia says
> 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.
-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.
+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 mocking the singleton could be difficult.
**Programmatic Example**
To create a singleton, make the constructor private, disable cloning, disable extension and create a static variable to house the instance
```php
-final class President {
+final class President
+{
private static $instance;
- private function __construct() {
+ private function __construct()
+ {
// Hide the constructor
}
-
- public static function getInstance() : President {
- if ($this->instance) {
- return $this->instance;
+
+ public static function getInstance(): President
+ {
+ if (!self::$instance) {
+ self::$instance = new self();
}
-
- $this->instance = new President();
- return $this->instance;
+
+ return self::$instance;
}
-
- private function __clone() {
+
+ private function __clone()
+ {
// Disable cloning
}
+
+ private function __wakeup()
+ {
+ // Disable unserialize
+ }
}
```
Then in order to use
@@ -481,7 +595,7 @@ In plain words
Wikipedia says
> In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities.
-
+
* [Adapter](#-adapter)
* [Bridge](#-bridge)
* [Composite](#-composite)
@@ -510,43 +624,59 @@ Consider a game where there is a hunter and he hunts lions.
First we have an interface `Lion` that all types of lions have to implement
```php
-interface Lion {
+interface Lion
+{
public function roar();
}
-class AfricanLion implements Lion {
- public function roar() {}
+class AfricanLion implements Lion
+{
+ public function roar()
+ {
+ }
}
-class AsianLion implements Lion {
- public function roar() {}
+class AsianLion implements Lion
+{
+ public function roar()
+ {
+ }
}
```
And hunter expects any implementation of `Lion` interface to hunt.
```php
-class Hunter {
- public function hunt(Lion $lion) {
+class Hunter
+{
+ public function hunt(Lion $lion)
+ {
+ $lion->roar();
}
}
```
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
-
+
```php
// This needs to be added to the game
-class WildDog {
- public function bark() {}
+class WildDog
+{
+ public function bark()
+ {
+ }
}
// Adapter around wild dog to make it compatible with our game
-class WildDogAdapter implements Lion {
+class WildDogAdapter implements Lion
+{
protected $dog;
- public function __construct(WildDog $dog) {
+ public function __construct(WildDog $dog)
+ {
$this->dog = $dog;
}
-
- public function roar() {
+
+ public function roar()
+ {
$this->dog->bark();
}
}
@@ -566,7 +696,7 @@ $hunter->hunt($wildDogAdapter);
Real world example
> 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.
-
+
In Plain Words
> Bridge pattern is about preferring composition over inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy.
@@ -579,53 +709,68 @@ Wikipedia says
Translating our WebPage example from above. Here we have the `WebPage` hierarchy
```php
-interface WebPage {
+interface WebPage
+{
public function __construct(Theme $theme);
public function getContent();
}
-class About implements WebPage {
+class About implements WebPage
+{
protected $theme;
-
- public function __construct(Theme $theme) {
+
+ public function __construct(Theme $theme)
+ {
$this->theme = $theme;
}
-
- public function getContent() {
+
+ public function getContent()
+ {
return "About page in " . $this->theme->getColor();
}
}
-class Careers implements WebPage {
- protected $theme;
-
- public function __construct(Theme $theme) {
- $this->theme = $theme;
- }
-
- public function getContent() {
- return "Careers page in " . $this->theme->getColor();
- }
+class Careers implements WebPage
+{
+ protected $theme;
+
+ public function __construct(Theme $theme)
+ {
+ $this->theme = $theme;
+ }
+
+ public function getContent()
+ {
+ return "Careers page in " . $this->theme->getColor();
+ }
}
```
And the separate theme hierarchy
```php
-interface Theme {
+
+interface Theme
+{
public function getColor();
}
-class DarkTheme implements Theme {
- public function getColor() {
+class DarkTheme implements Theme
+{
+ public function getColor()
+ {
return 'Dark Black';
}
}
-class LightTheme implements Theme {
- public function getColor() {
+class LightTheme implements Theme
+{
+ public function getColor()
+ {
return 'Off white';
}
}
-class AquaTheme implements Theme {
- public function getColor() {
+class AquaTheme implements Theme
+{
+ public function getColor()
+ {
return 'Light blue';
}
}
@@ -641,14 +786,14 @@ echo $about->getContent(); // "About page in Dark Black";
echo $careers->getContent(); // "Careers page in Dark Black";
```
-๐ฟ Composite Pattern
+๐ฟ Composite
-----------------
Real world example
-> Every organization is composed of employees. Each of the employees has 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.
+> 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.
In plain words
-> Composite pattern lets clients to treat the individual objects in a uniform manner.
+> Composite pattern lets clients treat the individual objects in a uniform manner.
Wikipedia says
> 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.
@@ -658,66 +803,78 @@ Wikipedia says
Taking our employees example from above. Here we have different employee types
```php
-
-interface Employee {
+interface Employee
+{
public function __construct(string $name, float $salary);
- public function getName() : string;
+ public function getName(): string;
public function setSalary(float $salary);
- public function getSalary() : float;
- public function getRoles() : array;
+ public function getSalary(): float;
+ public function getRoles(): array;
}
-class Developer implements Employee {
-
+class Developer implements Employee
+{
protected $salary;
protected $name;
-
- public function __construct(string $name, float $salary) {
+ protected $roles;
+
+ public function __construct(string $name, float $salary)
+ {
$this->name = $name;
$this->salary = $salary;
}
- public function getName() : string {
+ public function getName(): string
+ {
return $this->name;
}
- public function setSalary(float $salary) {
+ public function setSalary(float $salary)
+ {
$this->salary = $salary;
}
- public function getSalary() : float {
+ public function getSalary(): float
+ {
return $this->salary;
}
- public function getRoles() : array {
- reutrn $this->roles
+ public function getRoles(): array
+ {
+ return $this->roles;
}
}
-class Designer implements Employee {
-
+class Designer implements Employee
+{
protected $salary;
protected $name;
+ protected $roles;
- public function __construct(string $name, float $salary) {
+ public function __construct(string $name, float $salary)
+ {
$this->name = $name;
$this->salary = $salary;
}
- public function getName() : string {
+ public function getName(): string
+ {
return $this->name;
}
- public function setSalary(float $salary) {
+ public function setSalary(float $salary)
+ {
$this->salary = $salary;
}
- public function getSalary() : float {
+ public function getSalary(): float
+ {
return $this->salary;
}
- public function getRoles() : array {
- reutrn $this->roles
+ public function getRoles(): array
+ {
+ return $this->roles;
}
}
```
@@ -725,15 +882,17 @@ class Designer implements Employee {
Then we have an organization which consists of several different types of employees
```php
-class Organization {
-
+class Organization
+{
protected $employees;
- public function addEmployee(Employee $employee) {
+ public function addEmployee(Employee $employee)
+ {
$this->employees[] = $employee;
}
- public function getNetSalaries() : float {
+ public function getNetSalaries(): float
+ {
$netSalary = 0;
foreach ($this->employees as $employee) {
@@ -750,14 +909,14 @@ And then it can be used as
```php
// Prepare the employees
$john = new Developer('John Doe', 12000);
-$jane = new Designer('Jane', 10000);
+$jane = new Designer('Jane Doe', 15000);
// Add them to organization
$organization = new Organization();
$organization->addEmployee($john);
$organization->addEmployee($jane);
-echo "Net salaries: " . $organization->getNetSalaries(); // Net Salaries: 22000
+echo "Net salaries: " . $organization->getNetSalaries(); // Net Salaries: 27000
```
โ Decorator
@@ -778,75 +937,86 @@ Wikipedia says
Lets take coffee for example. First of all we have a simple coffee implementing the coffee interface
```php
-interface Coffee {
+interface Coffee
+{
public function getCost();
public function getDescription();
}
-class SimpleCoffee implements Coffee {
-
- public function getCost() {
+class SimpleCoffee implements Coffee
+{
+ public function getCost()
+ {
return 10;
}
- public function getDescription() {
+ public function getDescription()
+ {
return 'Simple coffee';
}
}
```
We want to make the code extensible to allow options to modify it if required. Lets make some add-ons (decorators)
```php
-class MilkCoffee implements Coffee {
-
+class MilkCoffee implements Coffee
+{
protected $coffee;
- public function __construct(Coffee $coffee) {
+ public function __construct(Coffee $coffee)
+ {
$this->coffee = $coffee;
}
- public function getCost() {
+ public function getCost()
+ {
return $this->coffee->getCost() + 2;
}
- public function getDescription() {
- return $this->coffee->getDescription() + ', milk';
+ public function getDescription()
+ {
+ return $this->coffee->getDescription() . ', milk';
}
}
-class WhipCoffee implements Coffee {
-
+class WhipCoffee implements Coffee
+{
protected $coffee;
- public function __construct(Coffee $coffee) {
+ public function __construct(Coffee $coffee)
+ {
$this->coffee = $coffee;
}
- public function getCost() {
+ public function getCost()
+ {
return $this->coffee->getCost() + 5;
}
- public function getDescription() {
- return $this->coffee->getDescription() + ', whip';
+ public function getDescription()
+ {
+ return $this->coffee->getDescription() . ', whip';
}
}
-class VanillaCoffee implements Coffee {
-
+class VanillaCoffee implements Coffee
+{
protected $coffee;
- public function __construct(Coffee $coffee) {
+ public function __construct(Coffee $coffee)
+ {
$this->coffee = $coffee;
}
- public function getCost() {
+ public function getCost()
+ {
return $this->coffee->getCost() + 3;
}
- public function getDescription() {
- return $this->coffee->getDescription() + ', vanilla';
+ public function getDescription()
+ {
+ return $this->coffee->getDescription() . ', vanilla';
}
}
-
```
Lets make a coffee now
@@ -869,7 +1039,7 @@ echo $someCoffee->getCost(); // 20
echo $someCoffee->getDescription(); // Simple Coffee, milk, whip, vanilla
```
-๐ฆ Facade Pattern
+๐ฆ Facade
----------------
Real world example
@@ -882,36 +1052,44 @@ Wikipedia says
> A facade is an object that provides a simplified interface to a larger body of code, such as a class library.
**Programmatic Example**
+
Taking our computer example from above. Here we have the computer class
```php
-class Computer {
-
- public function getElectricShock() {
+class Computer
+{
+ public function getElectricShock()
+ {
echo "Ouch!";
}
- public function makeSound() {
+ public function makeSound()
+ {
echo "Beep beep!";
}
- public function showLoadingScreen() {
+ public function showLoadingScreen()
+ {
echo "Loading..";
}
- public function bam() {
+ public function bam()
+ {
echo "Ready to be used!";
}
- public function closeEverything() {
+ public function closeEverything()
+ {
echo "Bup bup bup buzzzz!";
}
- public function sooth() {
+ public function sooth()
+ {
echo "Zzzzz";
}
- public function pullCurrent() {
+ public function pullCurrent()
+ {
echo "Haaah!";
}
}
@@ -922,18 +1100,21 @@ class ComputerFacade
{
protected $computer;
- public function __construct(Computer $computer) {
+ public function __construct(Computer $computer)
+ {
$this->computer = $computer;
}
- public function turnOn() {
+ public function turnOn()
+ {
$this->computer->getElectricShock();
$this->computer->makeSound();
$this->computer->showLoadingScreen();
$this->computer->bam();
}
- public function turnOff() {
+ public function turnOff()
+ {
$this->computer->closeEverything();
$this->computer->pullCurrent();
$this->computer->sooth();
@@ -944,7 +1125,7 @@ Now to use the facade
```php
$computer = new ComputerFacade(new Computer());
$computer->turnOn(); // Ouch! Beep beep! Loading.. Ready to be used!
-$compuer->turnOff(); // Bup bup buzzz! Haah! Zzzzz
+$computer->turnOff(); // Bup bup buzzz! Haah! Zzzzz
```
๐ Flyweight
@@ -960,19 +1141,23 @@ Wikipedia says
> 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.
**Programmatic example**
+
Translating our tea example from above. First of all we have tea types and tea maker
```php
-// Anything that will be cached is flyweight.
+// Anything that will be cached is flyweight.
// Types of tea here will be flyweights.
-class KarakTea {
+class KarakTea
+{
}
// Acts as a factory and saves the tea
-class TeaMaker {
+class TeaMaker
+{
protected $availableTea = [];
- public function make($preference) {
+ public function make($preference)
+ {
if (empty($this->availableTea[$preference])) {
$this->availableTea[$preference] = new KarakTea();
}
@@ -985,21 +1170,24 @@ class TeaMaker {
Then we have the `TeaShop` which takes orders and serves them
```php
-class TeaShop {
-
+class TeaShop
+{
protected $orders;
protected $teaMaker;
- public function __construct(TeaMaker $teaMaker) {
+ public function __construct(TeaMaker $teaMaker)
+ {
$this->teaMaker = $teaMaker;
}
- public function takeOrder(string $teaType, int $table) {
+ public function takeOrder(string $teaType, int $table)
+ {
$this->orders[$table] = $this->teaMaker->make($teaType);
}
- public function serve() {
- foreach($this->orders as $table => $tea) {
+ public function serve()
+ {
+ foreach ($this->orders as $table => $tea) {
echo "Serving tea to table# " . $table;
}
}
@@ -1008,7 +1196,8 @@ class TeaShop {
And it can be used as below
```php
-$shop = new TeaShop();
+$teaMaker = new TeaMaker();
+$shop = new TeaShop($teaMaker);
$shop->takeOrder('less sugar', 1);
$shop->takeOrder('more milk', 2);
@@ -1023,68 +1212,78 @@ $shop->serve();
๐ฑ Proxy
-------------------
Real world example
-> Have you ever used access card to enter 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. Here door's main functionality is to open but there is a proxy added on top of it to add some additional functionality to the door. Let me better explain it using the code example below.
+> 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.
In plain words
-> In proxy pattern a class represents the functionality of another class.
+> Using the proxy pattern, a class represents the functionality of another class.
Wikipedia says
> 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.
**Programmatic Example**
+
Taking our security door example from above. Firstly we have the door interface and an implementation of door
```php
-interface Door {
+interface Door
+{
public function open();
public function close();
}
-class LabDoor implements Door {
- public function open() {
+class LabDoor implements Door
+{
+ public function open()
+ {
echo "Opening lab door";
}
- public function close() {
+ public function close()
+ {
echo "Closing the lab door";
}
}
```
Then we have a proxy to secure any doors that we want
```php
-class Security {
+class SecuredDoor implements Door
+{
protected $door;
- public function __construct(Door $door) {
+ public function __construct(Door $door)
+ {
$this->door = $door;
}
- public function open($password) {
+ public function open($password)
+ {
if ($this->authenticate($password)) {
$this->door->open();
} else {
- echo "Big no! It ain't possible.";
+ echo "Big no! It ain't possible.";
}
}
- public function authenticate($password) {
- return $password === '$ecr@t'
+ public function authenticate($password)
+ {
+ return $password === '$ecr@t';
}
- public function close() {
+ public function close()
+ {
$this->door->close();
}
}
```
And here is how it can be used
```php
-$door = new Security(new LabDoor());
+$door = new SecuredDoor(new LabDoor());
$door->open('invalid'); // Big no! It ain't possible.
$door->open('$ecr@t'); // Opening lab door
-$door->close('Closing lab door');
+$door->close(); // Closing lab door
```
-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`.
+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`.
Behavioral Design Patterns
==========================
@@ -1110,7 +1309,7 @@ Wikipedia says
-----------------------
Real world example
-> 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.
+> 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.
In plain words
> 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.
@@ -1123,51 +1322,61 @@ Wikipedia says
Translating our account example above. First of all we have a base account having the logic for chaining the accounts together and some accounts
```php
-abstract class Account {
+abstract class Account
+{
protected $successor;
protected $balance;
- public function setNext(Account $account) {
+ public function setNext(Account $account)
+ {
$this->successor = $account;
}
-
- public function pay(float $amountToPay) {
+
+ public function pay(float $amountToPay)
+ {
if ($this->canPay($amountToPay)) {
- echo sprintf('Paid %s using %s' . PHP_EOL, $amount, get_called_class());
- } else if ($this->successor) {
+ echo sprintf('Paid %s using %s' . PHP_EOL, $amountToPay, get_called_class());
+ } elseif ($this->successor) {
echo sprintf('Cannot pay using %s. Proceeding ..' . PHP_EOL, get_called_class());
$this->successor->pay($amountToPay);
} else {
- throw Exception('None of the accounts have enough balance');
+ throw new Exception('None of the accounts have enough balance');
}
}
-
- public function canPay($amount) : bool {
- return $this->balance <= $amount;
+
+ public function canPay($amount): bool
+ {
+ return $this->balance >= $amount;
}
}
-class Bank extends Account {
+class Bank extends Account
+{
protected $balance;
- public function __construct(float $balance) {
- $this->$balance = $balance;
+ public function __construct(float $balance)
+ {
+ $this->balance = $balance;
}
}
-class Paypal extends Account {
+class Paypal extends Account
+{
protected $balance;
- public function __construct(float $balance) {
- $this->$balance = $balance;
+ public function __construct(float $balance)
+ {
+ $this->balance = $balance;
}
}
-class Bitcoin extends Account {
+class Bitcoin extends Account
+{
protected $balance;
- public function __construct(float $balance) {
- $this->$balance = $balance;
+ public function __construct(float $balance)
+ {
+ $this->balance = $balance;
}
}
```
@@ -1195,7 +1404,7 @@ $bank->pay(259);
// Output will be
// ==============
// Cannot pay using bank. Proceeding ..
-// Cannot pay using paypal. Proceeding ..:
+// Cannot pay using paypal. Proceeding ..:
// Paid 259 using Bitcoin!
```
@@ -1203,7 +1412,7 @@ $bank->pay(259);
-------
Real world example
-> 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.
+> A generic example would be you ordering food at a 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.
> Another example would be you (i.e. `Client`) switching on (i.e. `Command`) the television (i.e. `Receiver`) using a remote control (`Invoker`).
In plain words
@@ -1217,61 +1426,75 @@ Wikipedia says
First of all we have the receiver that has the implementation of every action that could be performed
```php
// Receiver
-class Bulb {
- public function turnOn() {
+class Bulb
+{
+ public function turnOn()
+ {
echo "Bulb has been lit";
}
-
- public function turnOff() {
+
+ public function turnOff()
+ {
echo "Darkness!";
}
}
```
then we have an interface that each of the commands are going to implement and then we have a set of commands
```php
-interface Command {
+interface Command
+{
public function execute();
public function undo();
public function redo();
}
// Command
-class TurnOn implements Command {
+class TurnOn implements Command
+{
protected $bulb;
-
- public function __construct(Bulb $bulb) {
+
+ public function __construct(Bulb $bulb)
+ {
$this->bulb = $bulb;
}
-
- public function execute() {
+
+ public function execute()
+ {
$this->bulb->turnOn();
}
-
- public function undo() {
+
+ public function undo()
+ {
$this->bulb->turnOff();
}
-
- public function redo() {
+
+ public function redo()
+ {
$this->execute();
}
}
-class TurnOff implements Command {
+class TurnOff implements Command
+{
protected $bulb;
-
- public function __construct(Bulb $bulb) {
+
+ public function __construct(Bulb $bulb)
+ {
$this->bulb = $bulb;
}
-
- public function execute() {
+
+ public function execute()
+ {
$this->bulb->turnOff();
}
-
- public function undo() {
+
+ public function undo()
+ {
$this->bulb->turnOn();
}
-
- public function redo() {
+
+ public function redo()
+ {
$this->execute();
}
}
@@ -1279,9 +1502,10 @@ class TurnOff implements Command {
Then we have an `Invoker` with whom the client will interact to process any commands
```php
// Invoker
-class RemoteControl {
-
- public function submit(Command $command) {
+class RemoteControl
+{
+ public function submit(Command $command)
+ {
$command->execute();
}
}
@@ -1290,15 +1514,15 @@ Finally let's see how we can use it in our client
```php
$bulb = new Bulb();
-$turnOn = new TurnOnCommand($bulb);
-$turnOff = new TurnOffCommand($bulb);
+$turnOn = new TurnOn($bulb);
+$turnOff = new TurnOff($bulb);
$remote = new RemoteControl();
-$remoteControl->submit($turnOn); // Bulb has been lit!
-$remoteControl->submit($turnOff); // Darkness!
+$remote->submit($turnOn); // Bulb has been lit!
+$remote->submit($turnOff); // Darkness!
```
-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.
+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.
โฟ Iterator
--------
@@ -1313,17 +1537,21 @@ Wikipedia says
> 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.
**Programmatic example**
+
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`
```php
-class RadioStation {
+class RadioStation
+{
protected $frequency;
- public function __construct(float $frequency) {
- $this->frequency = $frequency;
+ public function __construct(float $frequency)
+ {
+ $this->frequency = $frequency;
}
-
- public function getFrequency() : float {
+
+ public function getFrequency(): float
+ {
return $this->frequency;
}
}
@@ -1334,44 +1562,52 @@ Then we have our iterator
use Countable;
use Iterator;
-class StationList implements Countable, Iterator {
+class StationList implements Countable, Iterator
+{
/** @var RadioStation[] $stations */
protected $stations = [];
-
+
/** @var int $counter */
protected $counter;
-
- public function addStation(RadioStation $station) {
+
+ public function addStation(RadioStation $station)
+ {
$this->stations[] = $station;
}
-
- public funtion removeStation(RadioStation $toRemove) {
+
+ public function removeStation(RadioStation $toRemove)
+ {
$toRemoveFrequency = $toRemove->getFrequency();
$this->stations = array_filter($this->stations, function (RadioStation $station) use ($toRemoveFrequency) {
return $station->getFrequency() !== $toRemoveFrequency;
});
}
-
- public function count() : int {
+
+ public function count(): int
+ {
return count($this->stations);
}
-
- public function current() : RadioStation {
+
+ public function current(): RadioStation
+ {
return $this->stations[$this->counter];
}
-
- public function key() {
+
+ public function key()
+ {
return $this->counter;
}
-
- public function next() {
+
+ public function next()
+ {
$this->counter++;
}
-
- public function rewind() {
+
+ public function rewind()
+ {
$this->counter = 0;
}
-
+
public function valid(): bool
{
return isset($this->stations[$this->counter]);
@@ -1382,40 +1618,47 @@ And then it can be used as
```php
$stationList = new StationList();
-$stationList->addStation(new Station(89));
-$stationList->addStation(new Station(101));
-$stationList->addStation(new Station(102));
-$stationList->addStation(new Station(103.2));
+$stationList->addStation(new RadioStation(89));
+$stationList->addStation(new RadioStation(101));
+$stationList->addStation(new RadioStation(102));
+$stationList->addStation(new RadioStation(103.2));
foreach($stationList as $station) {
echo $station->getFrequency() . PHP_EOL;
}
-$stationList->removeStation(new Station(89)); // Will remove station 89
+$stationList->removeStation(new RadioStation(89)); // Will remove station 89
```
๐ฝ Mediator
========
Real world example
-> 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.
+> 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.
In plain words
-> 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.
+> 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.
Wikipedia says
> 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.
**Programmatic Example**
-Here is the simplest example of a chat room (i.e. mediator) with users (i.e. colleagues) sending messages to each other.
+Here is the simplest example of a chat room (i.e. mediator) with users (i.e. colleagues) sending messages to each other.
-First of all, we have the mediator i.e. the chat room
+First of all, we have the mediator i.e. the chat room
```php
+interface ChatRoomMediator
+{
+ public function showMessage(User $user, string $message);
+}
+
// Mediator
-class ChatRoom implements ChatRoomMediator {
- public function showMessage(User $user, string $message) {
+class ChatRoom implements ChatRoomMediator
+{
+ public function showMessage(User $user, string $message)
+ {
$time = date('M d, y H:i');
$sender = $user->getName();
@@ -1434,11 +1677,11 @@ class User {
$this->name = $name;
$this->chatMediator = $chatMediator;
}
-
+
public function getName() {
return $this->name;
}
-
+
public function send($message) {
$this->chatMediator->showMessage($this, $message);
}
@@ -1462,7 +1705,7 @@ $jane->send('Hey!');
๐พ Memento
-------
Real world example
-> 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).
+> 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).
In plain words
> 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.
@@ -1479,14 +1722,17 @@ Lets take an example of text editor which keeps saving the state from time to ti
First of all we have our memento object that will be able to hold the editor state
```php
-class EditorMemento {
+class EditorMemento
+{
protected $content;
-
- public function __construct(string $content) {
+
+ public function __construct(string $content)
+ {
$this->content = $content;
}
-
- public function getContent() {
+
+ public function getContent()
+ {
return $this->content;
}
}
@@ -1495,28 +1741,33 @@ class EditorMemento {
Then we have our editor i.e. originator that is going to use memento object
```php
-class Editor {
+class Editor
+{
protected $content = '';
-
- public function type(string $words) {
+
+ public function type(string $words)
+ {
$this->content = $this->content . ' ' . $words;
}
-
- public function getContent() {
+
+ public function getContent()
+ {
return $this->content;
}
-
- public function save() {
+
+ public function save()
+ {
return new EditorMemento($this->content);
}
-
- public function restore(EditorMemento $memento) {
+
+ public function restore(EditorMemento $memento)
+ {
$this->content = $memento->getContent();
}
}
```
-And then it can be used as
+And then it can be used as
```php
$editor = new Editor();
@@ -1555,26 +1806,32 @@ Wikipedia says
Translating our example from above. First of all we have job seekers that need to be notified for a job posting
```php
-class JobPost {
+class JobPost
+{
protected $title;
-
- public function __construct(string $title) {
+
+ public function __construct(string $title)
+ {
$this->title = $title;
}
-
- public function getTitle() {
+
+ public function getTitle()
+ {
return $this->title;
}
}
-class JobSeeker implements Observer {
+class JobSeeker implements Observer
+{
protected $name;
- public function __construct(string $name) {
+ public function __construct(string $name)
+ {
$this->name = $name;
}
- public function onJobPosted(JobPosting $job) {
+ public function onJobPosted(JobPost $job)
+ {
// Do something with the job posting
echo 'Hi ' . $this->name . '! New job posted: '. $job->getTitle();
}
@@ -1582,20 +1839,24 @@ class JobSeeker implements Observer {
```
Then we have our job postings to which the job seekers will subscribe
```php
-class JobPostings implements Observable {
+class EmploymentAgency implements Observable
+{
protected $observers = [];
-
- protected function notify(JobPost $jobPosting) {
+
+ protected function notify(JobPost $jobPosting)
+ {
foreach ($this->observers as $observer) {
$observer->onJobPosted($jobPosting);
}
}
-
- public function attach(Observer $observer) {
+
+ public function attach(Observer $observer)
+ {
$this->observers[] = $observer;
}
-
- public function addJob(JobPost $jobPosting) {
+
+ public function addJob(JobPost $jobPosting)
+ {
$this->notify($jobPosting);
}
}
@@ -1605,12 +1866,11 @@ Then it can be used as
// Create subscribers
$johnDoe = new JobSeeker('John Doe');
$janeDoe = new JobSeeker('Jane Doe');
-$kaneDoe = new JobSeeker('Kane Doe');
// Create publisher and attach subscribers
-$jobPostings = new JobPostings();
-$jobPostings->attatch($johnDoe);
-$jobPostings->attatch($janeDoe);
+$jobPostings = new EmploymentAgency();
+$jobPostings->attach($johnDoe);
+$jobPostings->attach($janeDoe);
// Add a new job and see if subscribers get notified
$jobPostings->addJob(new JobPost('Software Engineer'));
@@ -1623,26 +1883,28 @@ $jobPostings->addJob(new JobPost('Software Engineer'));
๐ Visitor
-------
Real world example
-> 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 let's 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.
+> 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.
In plain words
-> Visitor pattern let's you add further operations to objects without having to modify them.
-
+> Visitor pattern lets you add further operations to objects without having to modify them.
+
Wikipedia says
> 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.
**Programmatic example**
-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
+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
```php
// Visitee
-interface Animal {
+interface Animal
+{
public function accept(AnimalOperation $operation);
}
// Visitor
-interface AnimalOperation {
+interface AnimalOperation
+{
public function visitMonkey(Monkey $monkey);
public function visitLion(Lion $lion);
public function visitDolphin(Dolphin $dolphin);
@@ -1650,49 +1912,61 @@ interface AnimalOperation {
```
Then we have our implementations for the animals
```php
-class Monkey {
-
- public function shout() {
+class Monkey implements Animal
+{
+ public function shout()
+ {
echo 'Ooh oo aa aa!';
}
- public function accept(AnimalOperation $operation) {
+ public function accept(AnimalOperation $operation)
+ {
$operation->visitMonkey($this);
}
}
-class Lion {
- public function roar() {
+class Lion implements Animal
+{
+ public function roar()
+ {
echo 'Roaaar!';
}
-
- public function accept(AnimalOperation $operation) {
+
+ public function accept(AnimalOperation $operation)
+ {
$operation->visitLion($this);
}
}
-class Dolphin {
- public function speak() {
+class Dolphin implements Animal
+{
+ public function speak()
+ {
echo 'Tuut tuttu tuutt!';
}
-
- public function accept(AnimalOperation $operation) {
+
+ public function accept(AnimalOperation $operation)
+ {
$operation->visitDolphin($this);
}
}
```
Let's implement our visitor
```php
-class Speak implements AnimalOperation {
- public function visitMonkey(Monkey $monkey) {
+class Speak implements AnimalOperation
+{
+ public function visitMonkey(Monkey $monkey)
+ {
$monkey->shout();
}
-
- public function visitLion(Lion $lion) {
+
+ public function visitLion(Lion $lion)
+ {
$lion->roar();
}
-
- public function visitDolphin(Dolphin $dolphin) {
+
+ public function visitDolphin(Dolphin $dolphin)
+ {
$dolphin->speak();
}
}
@@ -1710,19 +1984,23 @@ $monkey->accept($speak); // Ooh oo aa aa!
$lion->accept($speak); // Roaaar!
$dolphin->accept($speak); // Tuut tutt tuutt!
```
-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.
+We could have done this simply by having an 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.
```php
-class Jump implements AnimalOperation {
- public function visitMonkey(Monkey $monkey) {
+class Jump implements AnimalOperation
+{
+ public function visitMonkey(Monkey $monkey)
+ {
echo 'Jumped 20 feet high! on to the tree!';
}
-
- public function visitLion(Lion $lion) {
+
+ public function visitLion(Lion $lion)
+ {
echo 'Jumped 7 feet! Back on the ground!';
}
-
- public function visitDolphin(Dolphin $dolphin) {
+
+ public function visitDolphin(Dolphin $dolphin)
+ {
echo 'Walked on water a little and disappeared';
}
}
@@ -1735,9 +2013,9 @@ $monkey->accept($speak); // Ooh oo aa aa!
$monkey->accept($jump); // Jumped 20 feet high! on to the tree!
$lion->accept($speak); // Roaaar!
-$lion->accept($jump); // Jumped 7 feet! Back on the ground!
+$lion->accept($jump); // Jumped 7 feet! Back on the ground!
-$dolphin->accept($speak); // Tuut tutt tuutt!
+$dolphin->accept($speak); // Tuut tutt tuutt!
$dolphin->accept($jump); // Walked on water a little and disappeared
```
@@ -1752,157 +2030,181 @@ In plain words
Wikipedia says
> 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.
-
+
**Programmatic example**
Translating our example from above. First of all we have our strategy interface and different strategy implementations
```php
-interface SortStrategy {
- public function sort(array $dataset) : array;
+interface SortStrategy
+{
+ public function sort(array $dataset): array;
}
-class BubbleSortStrategy {
- public function sort(array $dataset) : array {
+class BubbleSortStrategy implements SortStrategy
+{
+ public function sort(array $dataset): array
+ {
echo "Sorting using bubble sort";
-
+
// Do sorting
return $dataset;
}
-}
+}
-class QuickSortStrategy {
- public function sort(array $dataset) : array {
+class QuickSortStrategy implements SortStrategy
+{
+ public function sort(array $dataset): array
+ {
echo "Sorting using quick sort";
-
+
// Do sorting
return $dataset;
}
}
```
-
+
And then we have our client that is going to use any strategy
```php
-class Sorter {
- protected $sorter;
-
- public function __construct(SortStrategy $sorter) {
- $this->sorter = $sorter;
+class Sorter
+{
+ protected $sorterSmall;
+ protected $sorterBig;
+
+ public function __construct(SortStrategy $sorterSmall, SortStrategy $sorterBig)
+ {
+ $this->sorterSmall = $sorterSmall;
+ $this->sorterBig = $sorterBig;
}
-
- public function sort(array $dataset) : array {
- return $this->sorter->sort($dataset);
+
+ public function sort(array $dataset): array
+ {
+ if (count($dataset) > 5) {
+ return $this->sorterBig->sort($dataset);
+ } else {
+ return $this->sorterSmall->sort($dataset);
+ }
}
}
```
And it can be used as
```php
-$dataset = [1, 5, 4, 3, 2, 8];
+$smalldataset = [1, 3, 4, 2];
+$bigdataset = [1, 4, 3, 2, 8, 10, 5, 6, 9, 7];
+
+$sorter = new Sorter(new BubbleSortStrategy(), new QuickSortStrategy());
-$sorter = new Sorter(new BubbleSortStrategy());
$sorter->sort($dataset); // Output : Sorting using bubble sort
-$sorter = new Sorter(new QuickSortStrategy());
-$sorter->sort($dataset); // Output : Sorting using quick sort
+$sorter->sort($bigdataset); // Output : Sorting using quick sort
```
๐ข State
-----
Real world example
-> Imagine you are using some drawing application, you choose the paint brush to draw. Now the brush changes it's 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.
+> 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.
In plain words
> It lets you change the behavior of a class when the state changes.
Wikipedia says
> 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.
-> 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
+> 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.
**Programmatic example**
-Let's take an example of text editor, it let's 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.
-
-First of all we have our state interface and some state implementations
+Let's take an example of a phone. First of all we have our state interface and some state implementations
```php
-interface WritingState {
- public function write(string $words);
+interface PhoneState {
+ public function pickUp(): PhoneState;
+ public function hangUp(): PhoneState;
+ public function dial(): PhoneState;
}
-class UpperCase implements WritingState {
- public function write(string $words) {
- echo strtoupper($words);
+// states implementation
+class PhoneStateIdle implements PhoneState {
+ public function pickUp(): PhoneState {
+ return new PhoneStatePickedUp();
}
-}
-
-class LowerCase implements WritingState {
- public function write(string $words) {
- echo strtolower($words);
+ public function hangUp(): PhoneState {
+ throw new Exception("already idle");
+ }
+ public function dial(): PhoneState {
+ throw new Exception("unable to dial in idle state");
}
}
-class Default implements WritingState {
- public function write(string $words) {
- echo $words;
+class PhoneStatePickedUp implements PhoneState {
+ public function pickUp(): PhoneState {
+ throw new Exception("already picked up");
+ }
+ public function hangUp(): PhoneState {
+ return new PhoneStateIdle();
+ }
+ public function dial(): PhoneState {
+ return new PhoneStateCalling();
}
}
-```
-Then we have our editor
-```php
-class TextEditor {
- protected $state;
-
- public function __construct(WritingState $state) {
- $this->state = $state;
+
+class PhoneStateCalling implements PhoneState {
+ public function pickUp(): PhoneState {
+ throw new Exception("already picked up");
}
-
- public function setState(WritingState $state) {
- $this->state = $state;
+ public function hangUp(): PhoneState {
+ return new PhoneStateIdle();
}
-
- public function type(string $words) {
- $this->state->write($words);
+ public function dial(): PhoneState {
+ throw new Exception("already dialing");
}
}
```
-And then it can be used as
-```php
-$editor = new TextEditor(new Default());
-$editor->type('First line');
+Then we have our Phone class that changes the state on different behavior calls
-$editor->setState(new UpperCaseState());
+```php
+class Phone {
+ private $state;
-$editor->type('Second line');
-$editor->type('Third line');
+ public function __construct() {
+ $this->state = new PhoneStateIdle();
+ }
+ public function pickUp() {
+ $this->state = $this->state->pickUp();
+ }
+ public function hangUp() {
+ $this->state = $this->state->hangUp();
+ }
+ public function dial() {
+ $this->state = $this->state->dial();
+ }
+}
+```
-$editor->setState(new LowerCaseState());
+And then it can be used as follows and it will call the relevant state methods:
-$editor->type('Fourth line');
-$editor->type('Fifth line');
+```php
+$phone = new Phone();
-// Output:
-// First line
-// SECOND LINE
-// THIRD LINE
-// fourth line
-// fifth line
+$phone->pickUp();
+$phone->dial();
```
๐ Template Method
---------------
Real world example
-> Suppose we are getting some house built. The steps for building might look like
+> Suppose we are getting some house built. The steps for building might look like
> - Prepare the base of house
> - Build the walls
> - Add roof
> - Add other floors
+
> 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.
-
+
In plain words
-> Template method defines the skeleton of how certain algorithm could be performed but defers the implementation of those steps to the children classes.
-
+> Template method defines the skeleton of how a certain algorithm could be performed, but defers the implementation of those steps to the children classes.
+
Wikipedia says
> 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.
@@ -1912,58 +2214,70 @@ Imagine we have a build tool that helps us test, lint, build, generate build rep
First of all we have our base class that specifies the skeleton for the build algorithm
```php
-abstract class Builder {
-
- // Template method
- public final function build() {
+abstract class Builder
+{
+
+ // Template method
+ final public function build()
+ {
$this->test();
$this->lint();
$this->assemble();
$this->deploy();
}
-
- public abstract function test();
- public abstract function lint();
- public abstract function build();
- public abstract function deploy();
+
+ abstract public function test();
+ abstract public function lint();
+ abstract public function assemble();
+ abstract public function deploy();
}
```
Then we can have our implementations
```php
-class AndroidBuilder extends Builder {
- public function test() {
+class AndroidBuilder extends Builder
+{
+ public function test()
+ {
echo 'Running android tests';
}
-
- public function lint() {
+
+ public function lint()
+ {
echo 'Linting the android code';
}
-
- public function assemble() {
+
+ public function assemble()
+ {
echo 'Assembling the android build';
}
-
- public function deploy() {
+
+ public function deploy()
+ {
echo 'Deploying android build to server';
}
}
-class IosBuilder extends Builder {
- public function test() {
+class IosBuilder extends Builder
+{
+ public function test()
+ {
echo 'Running ios tests';
}
-
- public function lint() {
+
+ public function lint()
+ {
echo 'Linting the ios code';
}
-
- public function assemble() {
+
+ public function assemble()
+ {
echo 'Assembling the ios build';
}
-
- public function deploy() {
+
+ public function deploy()
+ {
echo 'Deploying ios build to server';
}
}
@@ -1999,7 +2313,8 @@ And that about wraps it up. I will continue to improve this, so you might want t
- Report issues
- Open pull request with improvements
- Spread the word
-- Reach out to me directly at kamranahmed.se@gmail.com or [@kamranahmedse](http://twitter.com/kamranahmedse)
+- Reach out with any feedback [](https://twitter.com/kamrify)
## License
-MIT ยฉ [Kamran Ahmed](https://kamranahmed.info)
+
+[](https://creativecommons.org/licenses/by/4.0/)