From d5473a78a2aba2e3280df3787edde3045ec188be Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Fri, 17 Feb 2017 10:12:45 +0400
Subject: [PATCH 01/93] Fix minor typo
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 07031cba..a447a254 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
π 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.
From 6c078d6a0f48d2e8717c8c6afcf7a1380bd913b9 Mon Sep 17 00:00:00 2001
From: Sven Luijten
Date: Fri, 17 Feb 2017 11:43:23 +0100
Subject: [PATCH 03/93] Fix facade, builder and composite section titles (#13)
* Fix facade section title
* Correct builder & composite links
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 1b989b91..9b4cded0 100644
--- a/README.md
+++ b/README.md
@@ -291,7 +291,7 @@ 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.
@@ -639,7 +639,7 @@ echo $about->getContent(); // "About page in Dark Black";
echo $careers->getContent(); // "Careers page in Dark Black";
```
-πΏ Composite Pattern
+πΏ Composite
-----------------
Real world example
@@ -867,7 +867,7 @@ echo $someCoffee->getCost(); // 20
echo $someCoffee->getDescription(); // Simple Coffee, milk, whip, vanilla
```
-π¦ Facade Pattern
+π¦ Facade
----------------
Real world example
From 75fd88eb4ab6cc3f4df5cff79bdf7b5e6c56e50a Mon Sep 17 00:00:00 2001
From: Luke Rodgers
Date: Fri, 17 Feb 2017 10:44:11 +0000
Subject: [PATCH 04/93] Fix singleton section typo (#15)
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 9b4cded0..2adfb2af 100644
--- a/README.md
+++ b/README.md
@@ -432,7 +432,7 @@ 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.
From b82c8484bf30eac3f313472af2b75026b7d8befc Mon Sep 17 00:00:00 2001
From: Bassam Ismail
Date: Fri, 17 Feb 2017 16:39:35 +0530
Subject: [PATCH 05/93] Update README.md (#18)
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 2adfb2af..7b3189ef 100644
--- a/README.md
+++ b/README.md
@@ -319,9 +319,9 @@ The sane alternative is to use the builder pattern.
class BurgerBuilder {
protected $size;
- protected $pepperoni = true;
protected $cheeze = true;
- protected $lettuce = true;
+ protected $pepperoni = false;
+ protected $lettuce = false;
protected $tomato = false;
public function __construct(int $size) {
From 972f749627844655c23c5af6e3c13151501fe437 Mon Sep 17 00:00:00 2001
From: Adnan Ahmed
Date: Fri, 17 Feb 2017 18:19:27 +0400
Subject: [PATCH 06/93] Fixed typo reutrn (#24)
* Fixed type reutrn
* Fixed typo
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 7b3189ef..eff67f43 100644
--- a/README.md
+++ b/README.md
@@ -688,7 +688,7 @@ class Developer implements Employee {
}
public function getRoles() : array {
- reutrn $this->roles
+ return $this->roles;
}
}
@@ -715,7 +715,7 @@ class Designer implements Employee {
}
public function getRoles() : array {
- reutrn $this->roles
+ return $this->roles;
}
}
```
From 1825f51643df03df0149492a7134da0e574a8206 Mon Sep 17 00:00:00 2001
From: LIQRGV
Date: Fri, 17 Feb 2017 21:41:29 +0700
Subject: [PATCH 07/93] Fix typo
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index eff67f43..515fb817 100644
--- a/README.md
+++ b/README.md
@@ -1760,7 +1760,7 @@ interface SortStrategy {
public function sort(array $dataset) : array;
}
-class BubbleSortStrategy {
+class BubbleSortStrategy implements SortStrategy {
public function sort(array $dataset) : array {
echo "Sorting using bubble sort";
@@ -1769,7 +1769,7 @@ class BubbleSortStrategy {
}
}
-class QuickSortStrategy {
+class QuickSortStrategy implements SortStrategy {
public function sort(array $dataset) : array {
echo "Sorting using quick sort";
From c8693a276f1c315c7b7c50386580d65be2bab8d3 Mon Sep 17 00:00:00 2001
From: Rupak
Date: Fri, 17 Feb 2017 15:43:52 +0100
Subject: [PATCH 08/93] Fix example so that it implements interface (#12)
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 515fb817..340009ee 100644
--- a/README.md
+++ b/README.md
@@ -1648,7 +1648,7 @@ interface AnimalOperation {
```
Then we have our implementations for the animals
```php
-class Monkey {
+class Monkey implements Animal {
public function shout() {
echo 'Ooh oo aa aa!';
@@ -1659,7 +1659,7 @@ class Monkey {
}
}
-class Lion {
+class Lion implements Animal {
public function roar() {
echo 'Roaaar!';
}
@@ -1669,7 +1669,7 @@ class Lion {
}
}
-class Dolphin {
+class Dolphin implements Animal {
public function speak() {
echo 'Tuut tuttu tuutt!';
}
From 89aff71c7db7ad76030b2c2c88ef412e2f8d4650 Mon Sep 17 00:00:00 2001
From: Sven Luijten
Date: Fri, 17 Feb 2017 15:48:31 +0100
Subject: [PATCH 09/93] Fix typos & clarify text in the 'Proxy' section (#19)
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 340009ee..fdcf8dde 100644
--- a/README.md
+++ b/README.md
@@ -1021,10 +1021,10 @@ $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.
@@ -1082,7 +1082,7 @@ $door->open('invalid'); // Big no! It ain't possible.
$door->open('$ecr@t'); // Opening 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
==========================
From 912e2aeba1e9b70890036d8cb8f33377184a4a59 Mon Sep 17 00:00:00 2001
From: Sven Luijten
Date: Fri, 17 Feb 2017 15:54:48 +0100
Subject: [PATCH 10/93] Host images on GitHub instead of imgur (#22)
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index fdcf8dde..5f9e33e0 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
+
***
-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.
+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
=================
-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 are solutions to recurring problems; guidelines on how to tackle certain problems
@@ -43,14 +43,14 @@ 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
@@ -66,35 +66,42 @@ 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
@@ -106,37 +113,42 @@ echo 'Height: ' . $door->getHeight();
**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';
}
}
@@ -145,27 +157,34 @@ class CommunityExecutive implements Interviewer {
Now let us create our `HiringManager`
```php
-abstract class HiringManager {
-
+abstract class HiringManager
+{
+
// Factory method
- abstract public function makeInterviewer() : Interviewer;
-
- public function takeInterview() {
+ abstract public 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
+{
+ public function makeInterviewer(): Interviewer
+ {
return new Developer();
}
}
-class MarketingManager extends HiringManager {
- public function makeInterviewer() : Interviewer {
+class MarketingManager extends HiringManager
+{
+ public function makeInterviewer(): Interviewer
+ {
return new CommunityExecutive();
}
}
@@ -191,8 +210,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
@@ -201,18 +220,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';
}
}
@@ -220,18 +244,23 @@ 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';
}
}
@@ -239,29 +268,36 @@ class Carpenter implements DoorFittingExpert {
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();
}
}
@@ -299,14 +335,15 @@ Real world example
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)
+{
}
```
@@ -317,15 +354,17 @@ As you can see; the number of constructor parameters can quickly get out of hand
The sane alternative is to use the builder pattern. First of all we have our burger that we want to make
```php
-class Burger {
+class Burger
+{
protected $size;
protected $cheese = false;
protected $pepperoni = false;
protected $lettuce = false;
protected $tomato = false;
-
- public function __construct(BurgerBuilder $builder) {
+
+ public function __construct(BurgerBuilder $builder)
+ {
$this->size = $builder->size;
$this->cheese = $builder->cheese;
$this->pepperoni = $builder->pepperoni;
@@ -338,7 +377,8 @@ class Burger {
And then we have the builder
```php
-class BurgerBuilder {
+class BurgerBuilder
+{
public $size;
public $cheese = false;
@@ -346,31 +386,37 @@ class BurgerBuilder {
public $lettuce = false;
public $tomato = false;
- public function __construct(int $size) {
+ 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 addCheese() {
+
+ public function addCheese()
+ {
$this->cheese = true;
return $this;
}
-
- public function addTomato() {
+
+ public function addTomato()
+ {
$this->tomato = true;
return $this;
}
-
- public function build() : Burger {
+
+ public function build(): Burger
+ {
return new Burger($this);
}
}
@@ -405,30 +451,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;
}
}
@@ -469,26 +521,31 @@ Singleton pattern is actually considered an anti-pattern and overuse of it shoul
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 {
+
+ public static function getInstance(): President
+ {
if (!self::$instance) {
self::$instance = new self();
}
-
+
return self::$instance;
}
-
- private function __clone() {
+
+ private function __clone()
+ {
// Disable cloning
}
-
- private function __wakeup() {
+
+ private function __wakeup()
+ {
// Disable unserialize
}
}
@@ -508,7 +565,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)
@@ -537,43 +594,58 @@ 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)
+ {
}
}
```
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();
}
}
@@ -606,53 +678,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';
}
}
@@ -685,65 +772,75 @@ 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) {
+ 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 {
+ public function getRoles(): array
+ {
return $this->roles;
}
}
-class Designer implements Employee {
-
+class Designer implements Employee
+{
protected $salary;
protected $name;
- 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 {
+ public function getRoles(): array
+ {
return $this->roles;
}
}
@@ -752,15 +849,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) {
@@ -805,75 +904,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() {
+ 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() {
+ 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() {
+ public function getDescription()
+ {
return $this->coffee->getDescription() . ', vanilla';
}
}
-
```
Lets make a coffee now
@@ -913,33 +1023,40 @@ Wikipedia says
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!";
}
}
@@ -950,18 +1067,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();
@@ -992,16 +1112,19 @@ Wikipedia says
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();
}
@@ -1014,21 +1137,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;
}
}
@@ -1066,43 +1192,52 @@ Wikipedia says
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 Security
+{
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) {
+ public function authenticate($password)
+ {
return $password === '$ecr@t';
}
- public function close() {
+ public function close()
+ {
$this->door->close();
}
}
@@ -1154,50 +1289,60 @@ 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, $amountToPay, get_called_class());
- } else if ($this->successor) {
+ } 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');
}
}
-
- public function canPay($amount) : bool {
+
+ public function canPay($amount): bool
+ {
return $this->balance >= $amount;
}
}
-class Bank extends Account {
+class Bank extends Account
+{
protected $balance;
- public function __construct(float $balance) {
+ public function __construct(float $balance)
+ {
$this->balance = $balance;
}
}
-class Paypal extends Account {
+class Paypal extends Account
+{
protected $balance;
- public function __construct(float $balance) {
+ public function __construct(float $balance)
+ {
$this->balance = $balance;
}
}
-class Bitcoin extends Account {
+class Bitcoin extends Account
+{
protected $balance;
- public function __construct(float $balance) {
+ public function __construct(float $balance)
+ {
$this->balance = $balance;
}
}
@@ -1226,7 +1371,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!
```
@@ -1234,7 +1379,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 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.
> 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
@@ -1248,61 +1393,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();
}
}
@@ -1310,9 +1469,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();
}
}
@@ -1329,7 +1489,7 @@ $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
--------
@@ -1348,14 +1508,17 @@ Wikipedia says
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;
}
}
@@ -1366,44 +1529,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 function 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]);
@@ -1430,24 +1601,26 @@ $stationList->removeStation(new RadioStation(89)); // Will remove station 89
========
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
// 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();
@@ -1466,11 +1639,11 @@ class User {
$this->name = $name;
$this->chatMediator = $chatMediator;
}
-
+
public function getName() {
return $this->name;
}
-
+
public function send($message) {
$this->chatMediator->showMessage($this, $message);
}
@@ -1494,7 +1667,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.
@@ -1511,14 +1684,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;
}
}
@@ -1527,28 +1703,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();
@@ -1587,26 +1768,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(JobPost $job) {
+ public function onJobPosted(JobPost $job)
+ {
// Do something with the job posting
echo 'Hi ' . $this->name . '! New job posted: '. $job->getTitle();
}
@@ -1614,20 +1801,24 @@ class JobSeeker implements Observer {
```
Then we have our job postings to which the job seekers will subscribe
```php
-class JobPostings implements Observable {
+class JobPostings 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);
}
}
@@ -1658,22 +1849,24 @@ Real world example
In plain words
> 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);
@@ -1681,49 +1874,61 @@ interface AnimalOperation {
```
Then we have our implementations for the animals
```php
-class Monkey implements Animal {
-
- 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 implements Animal {
- 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 implements Animal {
- 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();
}
}
@@ -1744,16 +1949,20 @@ $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.
```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';
}
}
@@ -1766,9 +1975,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
```
@@ -1783,45 +1992,53 @@ 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 implements SortStrategy {
- 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 implements SortStrategy {
- 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 {
+class Sorter
+{
protected $sorter;
-
- public function __construct(SortStrategy $sorter) {
+
+ public function __construct(SortStrategy $sorter)
+ {
$this->sorter = $sorter;
}
-
- public function sort(array $dataset) : array {
+
+ public function sort(array $dataset): array
+ {
return $this->sorter->sort($dataset);
}
}
@@ -1856,42 +2073,53 @@ Let's take an example of text editor, it lets you change the state of text that
First of all we have our state interface and some state implementations
```php
-interface WritingState {
+interface WritingState
+{
public function write(string $words);
}
-class UpperCase implements WritingState {
- public function write(string $words) {
- echo strtoupper($words);
+class UpperCase implements WritingState
+{
+ public function write(string $words)
+ {
+ echo strtoupper($words);
}
-}
+}
-class LowerCase implements WritingState {
- public function write(string $words) {
- echo strtolower($words);
+class LowerCase implements WritingState
+{
+ public function write(string $words)
+ {
+ echo strtolower($words);
}
}
-class Default implements WritingState {
- public function write(string $words) {
+class Default implements WritingState
+{
+ public function write(string $words)
+ {
echo $words;
}
}
```
Then we have our editor
```php
-class TextEditor {
+class TextEditor
+{
protected $state;
-
- public function __construct(WritingState $state) {
+
+ public function __construct(WritingState $state)
+ {
$this->state = $state;
}
-
- public function setState(WritingState $state) {
+
+ public function setState(WritingState $state)
+ {
$this->state = $state;
}
-
- public function type(string $words) {
+
+ public function type(string $words)
+ {
$this->state->write($words);
}
}
@@ -1924,17 +2152,17 @@ $editor->type('Fifth line');
---------------
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 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.
@@ -1944,58 +2172,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 assemble();
- 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';
}
}
From f11e7a92cae5922af8e53ec2c882645f1040d053 Mon Sep 17 00:00:00 2001
From: Greg Hovanesyan
Date: Sun, 5 Mar 2017 14:58:55 +0400
Subject: [PATCH 47/93] add missing interface to Mediator (#76)
---
README.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/README.md b/README.md
index fbd15d41..55a7e161 100644
--- a/README.md
+++ b/README.md
@@ -1616,6 +1616,11 @@ Here is the simplest example of a chat room (i.e. mediator) with users (i.e. col
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
{
From 3334e0d273839684ede164e81e1f059394fecd71 Mon Sep 17 00:00:00 2001
From: Greg Hovanesyan
Date: Sun, 5 Mar 2017 16:37:35 +0400
Subject: [PATCH 48/93] added "new" when throwing an exception (#77)
* add missing interface to Mediator
* add missing 'new' when throwing an Exception
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 55a7e161..1aed00c6 100644
--- a/README.md
+++ b/README.md
@@ -1307,7 +1307,7 @@ abstract class Account
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');
}
}
From 340368b90858e486ff1c38a1ff0f5e6befa9534f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20K=C3=B6nig?=
Date: Mon, 6 Mar 2017 04:51:44 +0100
Subject: [PATCH 49/93] Small typo fixes (#75)
* Small typo fixes
* Fix typo
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 1aed00c6..9b11200f 100644
--- a/README.md
+++ b/README.md
@@ -759,10 +759,10 @@ echo $careers->getContent(); // "Careers page in Dark Black";
-----------------
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.
From 606699e17e5009051ef464b66b6574189b428989 Mon Sep 17 00:00:00 2001
From: Prayag Verma
Date: Fri, 17 Mar 2017 18:19:40 +0530
Subject: [PATCH 50/93] Fix a typo (#79)
Replace a with an
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 9b11200f..063a7671 100644
--- a/README.md
+++ b/README.md
@@ -1951,7 +1951,7 @@ $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
From c3c14c5666fb7a353a48adfbc409337fec0bd56e Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Sun, 19 Mar 2017 23:52:48 +0400
Subject: [PATCH 51/93] Fix - Trailing asterisks
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 063a7671..5b25852d 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,14 @@

***
+
π 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 mind (and maybe mine) by explaining them in the simplest way possible.
+
***
π Introduction
From d3d3469d701dd95b220a036d0560122d178f551e Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Mon, 20 Mar 2017 08:58:38 +0400
Subject: [PATCH 52/93] Add the sponsor message
---
README.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/README.md b/README.md
index 5b25852d..37fd4035 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,11 @@
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.
+
+***
+
+
Want to learn something? Visit the sponsor Hugobots
+
***
π Introduction
From 6e349dd341b8ba6aeb4f162f6e103af5c51fec01 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Mon, 20 Mar 2017 09:56:01 +0400
Subject: [PATCH 53/93] Minor update
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 37fd4035..0ab32ebe 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-
Want to learn something? Visit the sponsor Hugobots
+
Want to learn something new? Visit Hugobots where I teach people
***
From ff9c771c98c242c21fa9ee98eab941437845d2eb Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Tue, 21 Mar 2017 21:31:16 +0400
Subject: [PATCH 54/93] Increase jane's salary
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 0ab32ebe..fff0f93d 100644
--- a/README.md
+++ b/README.md
@@ -883,7 +883,7 @@ 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();
From 412b404c52e9b82f2821e7f385cfb76bc2e2f5d2 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Wed, 12 Apr 2017 22:05:27 +0400
Subject: [PATCH 55/93] Update readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index fff0f93d..405b607b 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-
Want to learn something new? Visit Hugobots where I teach people
+
Ever wanted to make something big? Visit Hugobots for a dose of inspiration!
***
From dc8a9b1c212c53be61c7bed5e0fe54e4596d14fd Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Thu, 20 Apr 2017 19:39:06 +0400
Subject: [PATCH 56/93] Update readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 405b607b..97a5c21a 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-
Ever wanted to make something big? Visit Hugobots for a dose of inspiration!
+
Do you like startups or aspire to be a founder? We are releasing Hugobots soon. Make sure to subscribe!
Do you like startups or aspire to be a founder? We are releasing Hugobots soon. Make sure to subscribe!
+
Need similar content? We are releasing Hugobots soon. Make sure to subscribe!
***
From 662a2b6bf08c2a365f5f81ea61874ff5a41fe2de Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Sun, 7 May 2017 21:00:02 +0400
Subject: [PATCH 60/93] Minor update
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index f074cbfe..dcd1288c 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-
Need similar content? We are releasing Hugobots soon. Make sure to subscribe!
+
Did you like this guide and want more of the similar content? We are releasing Hugobots soon. Make sure to subscribe!
Did you like this guide and want more of the similar content? We are releasing Hugobots soon. Make sure to subscribe!
+
Did you like this guide and want more of the similar content? [Buy me a coffee](http://paypal.me/kamranahmedse) and subscribe to Hugobots!
***
@@ -2285,9 +2285,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 with any feedback [](https://twitter.com/kamranahmedse)
---
[](https://opensource.org/licenses/MIT)
-[](http://paypal.me/kamranahmedse)
-[](https://twitter.com/kamranahmedse)
From a4acbdfb1a32b0c2d9ec43890f3ec078fa63a829 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Tue, 19 Sep 2017 14:57:10 +0400
Subject: [PATCH 67/93] Minor updates
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 72503502..237de45c 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-
Did you like this guide and want more of the similar content? [Buy me a coffee](http://paypal.me/kamranahmedse) and subscribe to Hugobots!
+
Did you like this guide and want more of the similar content? Buy me a coffee and subscribe to Hugobots!
***
@@ -2287,6 +2287,6 @@ And that about wraps it up. I will continue to improve this, so you might want t
- Spread the word
- Reach out with any feedback [](https://twitter.com/kamranahmedse)
----
+## License
[](https://opensource.org/licenses/MIT)
From 31afd2e751cc6437845f1add056956539dd2fe2f Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Mon, 25 Sep 2017 10:17:26 +0400
Subject: [PATCH 68/93] Change license to creative commons
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 237de45c..eed239cf 100644
--- a/README.md
+++ b/README.md
@@ -2289,4 +2289,4 @@ And that about wraps it up. I will continue to improve this, so you might want t
## License
-[](https://opensource.org/licenses/MIT)
+[](https://creativecommons.org/licenses/by/4.0/)
From 700e569631a448a01dfbb553c74655f90fb433aa Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Mon, 25 Sep 2017 10:23:41 +0400
Subject: [PATCH 69/93] Remove license file
---
LICENSE | 7 -------
1 file changed, 7 deletions(-)
delete mode 100644 LICENSE
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.
From d6ffd414a4ba07a633938e4ad4849ad087b18759 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Wed, 4 Oct 2017 20:38:12 +0400
Subject: [PATCH 70/93] =?UTF-8?q?I=20don't=20like=20coffee,=20removing=20t?=
=?UTF-8?q?he=20link=20=E2=98=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index eed239cf..b6aa6d52 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-
Did you like this guide and want more of the similar content? Buy me a coffee and subscribe to Hugobots!
+
Did you like this guide and want more of the similar content? Subscribe for the launch of Hugobots!
***
From 3029a6cbfb38c68dcc6ed2d43a42b33bc322ef9d Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Thu, 5 Oct 2017 10:30:25 +0400
Subject: [PATCH 71/93] Twitter link update
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index b6aa6d52..9e912024 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-
Did you like this guide and want more of the similar content? Subscribe for the launch of Hugobots!
+
Did you like this guide and want more of the similar content? Subscribe for the launch of Hugobots or follow me on twitter!
***
From b7e9a2e86826cd227654eb23d415c98ddc06068d Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Thu, 16 Nov 2017 00:19:30 +0400
Subject: [PATCH 72/93] Add sponsor
---
README.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 9e912024..2da1d2b3 100644
--- a/README.md
+++ b/README.md
@@ -2287,6 +2287,10 @@ And that about wraps it up. I will continue to improve this, so you might want t
- Spread the word
- Reach out with any feedback [](https://twitter.com/kamranahmedse)
-## License
+## Sponsored By
+
+- [Highig - Think and its done](http://highig.com/)
+
+## License
[](https://creativecommons.org/licenses/by/4.0/)
From 057e43402641c09f3a410cb23cb337a16b8c9b5e Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Mon, 5 Feb 2018 10:14:25 +0100
Subject: [PATCH 73/93] Update proxy example
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 2da1d2b3..863ff4af 100644
--- a/README.md
+++ b/README.md
@@ -1222,7 +1222,7 @@ class LabDoor implements Door
```
Then we have a proxy to secure any doors that we want
```php
-class Security
+class SecuredDoor
{
protected $door;
@@ -1253,7 +1253,7 @@ class Security
```
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
From b866a7b20da7170385484f9a71afcc7bd5604f1c Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Tue, 20 Feb 2018 13:57:05 +0100
Subject: [PATCH 74/93] Fixes #109
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 863ff4af..d4953d7a 100644
--- a/README.md
+++ b/README.md
@@ -2108,7 +2108,7 @@ class LowerCase implements WritingState
}
}
-class Default implements WritingState
+class DefaultText implements WritingState
{
public function write(string $words)
{
@@ -2140,7 +2140,7 @@ class TextEditor
```
And then it can be used as
```php
-$editor = new TextEditor(new Default());
+$editor = new TextEditor(new DefaultText());
$editor->type('First line');
From 04091a1439a496a8cdd50d096fdda8107243db88 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Sat, 7 Apr 2018 02:50:23 +0200
Subject: [PATCH 75/93] Update banner
---
README.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index d4953d7a..3c85ea4e 100644
--- a/README.md
+++ b/README.md
@@ -12,9 +12,10 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-
Did you like this guide and want more of the similar content? Subscribe for the launch of Hugobots or follow me on twitter!
***
+Check out my [blog](http://kamranahmed.info) and say "hi" on [Twitter](https://twitter.com/kamranahmedse).
π Introduction
=================
From 404f07c9aea1927d7a059c50f563954f7f6e2575 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Sun, 8 Apr 2018 00:25:15 +0200
Subject: [PATCH 76/93] Update banner
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 3c85ea4e..b8ed31c7 100644
--- a/README.md
+++ b/README.md
@@ -9,12 +9,12 @@
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.
-
***
-
***
From fc1d134bdb0d4f11c3fc22c8897f60e663028167 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Thu, 7 Jun 2018 17:19:39 +0400
Subject: [PATCH 80/93] Remove banner
---
README.md | 4 ----
1 file changed, 4 deletions(-)
diff --git a/README.md b/README.md
index 7f4a984c..332f97c4 100644
--- a/README.md
+++ b/README.md
@@ -11,10 +11,6 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-
-
-***
-
Check out my [blog](http://kamranahmed.info) and say "hi" on [Twitter](https://twitter.com/kamranahmedse).
π Introduction
From e23317abc422e787032b692ed4e8a08c61058a7c Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Sat, 8 Sep 2018 20:12:46 +0400
Subject: [PATCH 81/93] Add badge
---
README.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 332f97c4..caa3fde4 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,9 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
Check out my [blog](http://kamranahmed.info) and say "hi" on [Twitter](https://twitter.com/kamranahmedse).
-π Introduction
+[](https://paypal.me/kamranahmedse)
+
+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.
From a6a2748754546a13fb8feb0df92fcbda5ffb8e97 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Sun, 9 Sep 2018 22:19:18 +0400
Subject: [PATCH 82/93] Remove badge
---
README.md | 2 --
1 file changed, 2 deletions(-)
diff --git a/README.md b/README.md
index caa3fde4..5584bbc5 100644
--- a/README.md
+++ b/README.md
@@ -13,8 +13,6 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
Check out my [blog](http://kamranahmed.info) and say "hi" on [Twitter](https://twitter.com/kamranahmedse).
-[](https://paypal.me/kamranahmedse)
-
Introduction
=================
From c459620d555fdf39302bff2f6fca591011e9245a Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Sat, 13 Oct 2018 20:07:56 +0400
Subject: [PATCH 83/93] Update factory pattern
---
README.md | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 5584bbc5..cad499a2 100644
--- a/README.md
+++ b/README.md
@@ -27,10 +27,11 @@ 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. Plus the **support for other languages is underway**.
+> 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
-----------------
@@ -58,7 +59,7 @@ Wikipedia says
π 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
@@ -110,9 +111,14 @@ class DoorFactory
```
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?**
From 5050fe7ce2da3d0dbcc2d4e9020ec64a97896292 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Thu, 29 Nov 2018 00:21:04 +0400
Subject: [PATCH 84/93] Remove sponsors section
---
README.md | 4 ----
1 file changed, 4 deletions(-)
diff --git a/README.md b/README.md
index cad499a2..1ccdc835 100644
--- a/README.md
+++ b/README.md
@@ -2291,10 +2291,6 @@ And that about wraps it up. I will continue to improve this, so you might want t
- Spread the word
- Reach out with any feedback [](https://twitter.com/kamranahmedse)
-## Sponsored By
-
-- [Highig - Think and its done](http://highig.com/)
-
## License
[](https://creativecommons.org/licenses/by/4.0/)
From e1a507ce14f9794bd02a5b309cc7f64d2b196219 Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Sun, 22 Nov 2020 23:44:49 +0400
Subject: [PATCH 85/93] Add funding info
---
.github/FUNDING.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 .github/FUNDING.yml
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]
From 77076db6ceafa11984c54768a032308016def7bf Mon Sep 17 00:00:00 2001
From: Amir Zpr <45946337+amirzpr@users.noreply.github.com>
Date: Sat, 27 Aug 2022 14:50:27 +0430
Subject: [PATCH 86/93] Proxy class has not implemented interface (#134)
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 1ccdc835..a724328d 100644
--- a/README.md
+++ b/README.md
@@ -1226,7 +1226,7 @@ class LabDoor implements Door
```
Then we have a proxy to secure any doors that we want
```php
-class SecuredDoor
+class SecuredDoor implements Door
{
protected $door;
From e0de93e60a9ca55e309f28942b6214128a08108b Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Thu, 27 Apr 2023 11:28:47 +0100
Subject: [PATCH 87/93] Add banner
---
.github/banner.svg | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .github/banner.svg
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 @@
+
From 739322eb8cf166cf9b7fd0cec7bb5df20766b8fa Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Thu, 27 Apr 2023 11:59:11 +0100
Subject: [PATCH 88/93] Fix broken banner
---
README.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index a724328d..94c7cf97 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,8 @@
-
+
+
+
+
+
***
From 65805a0802f46720ef21308e7556bedbb228b701 Mon Sep 17 00:00:00 2001
From: Lukas Schmid
Date: Thu, 27 Apr 2023 13:00:12 +0200
Subject: [PATCH 89/93] Added runtime decision to sorter (#137)
---
README.md | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index 94c7cf97..f39e9ae6 100644
--- a/README.md
+++ b/README.md
@@ -2052,28 +2052,35 @@ And then we have our client that is going to use any strategy
```php
class Sorter
{
- protected $sorter;
+ protected $sorterSmall;
+ protected $sorterBig;
- public function __construct(SortStrategy $sorter)
+ public function __construct(SortStrategy $sorterSmall, SortStrategy $sorterBig)
{
- $this->sorter = $sorter;
+ $this->sorterSmall = $sorterSmall;
+ $this->sorterBig = $sorterBig;
}
public function sort(array $dataset): array
{
- return $this->sorter->sort($dataset);
+ 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
From 8d7b9edd433c4094edcf4482211743f8b122201e Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Thu, 27 Apr 2023 12:06:53 +0100
Subject: [PATCH 90/93] Update state pattern implementation
---
README.md => readme.md | 107 ++++++++++++++++++++---------------------
1 file changed, 52 insertions(+), 55 deletions(-)
rename README.md => readme.md (97%)
diff --git a/README.md b/readme.md
similarity index 97%
rename from README.md
rename to readme.md
index f39e9ae6..66f63628 100644
--- a/README.md
+++ b/readme.md
@@ -2097,84 +2097,81 @@ Wikipedia says
**Programmatic example**
-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.
-
-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();
+ }
+ public function hangUp(): PhoneState {
+ throw new Exception("already idle");
+ }
+ public function dial(): PhoneState {
+ throw new Exception("unable to dial in idle state");
}
}
-class LowerCase implements WritingState
-{
- public function write(string $words)
- {
- echo strtolower($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();
}
}
-class DefaultText implements WritingState
-{
- public function write(string $words)
- {
- echo $words;
+class PhoneStateCalling implements PhoneState {
+ public function pickUp(): PhoneState {
+ throw new Exception("already picked up");
+ }
+ public function hangUp(): PhoneState {
+ return new PhoneStateIdle();
+ }
+ public function dial(): PhoneState {
+ throw new Exception("already dialing");
}
}
```
-Then we have our editor
+
+Then we have our Phone class that changes the state on different behavior calls
+
```php
-class TextEditor
-{
- protected $state;
+class Phone {
+ private $state;
- public function __construct(WritingState $state)
- {
- $this->state = $state;
+ public function __construct() {
+ $this->state = new PhoneStateIdle();
}
-
- public function setState(WritingState $state)
- {
- $this->state = $state;
+ public function pickUp() {
+ $this->state = $this->state->pickUp();
}
-
- public function type(string $words)
- {
- $this->state->write($words);
+ public function hangUp() {
+ $this->state = $this->state->hangUp();
+ }
+ public function dial() {
+ $this->state = $this->state->dial();
}
}
```
-And then it can be used as
-```php
-$editor = new TextEditor(new DefaultText());
-
-$editor->type('First line');
-
-$editor->setState(new UpperCase());
-$editor->type('Second line');
-$editor->type('Third line');
+And then it can be used as follows and it will call the relevant state methods:
-$editor->setState(new LowerCase());
-
-$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
From 5e44e6a7ce47e44c50fa4d6fb3bf6c5b1a85129b Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Thu, 27 Apr 2023 12:32:39 +0100
Subject: [PATCH 91/93] Update header
---
readme.md | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/readme.md b/readme.md
index 66f63628..4153f965 100644
--- a/readme.md
+++ b/readme.md
@@ -1,8 +1,7 @@
-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.
+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.
***
-Check out my [blog](http://kamranahmed.info) and say "hi" on [Twitter](https://twitter.com/kamranahmedse).
+Check out my [other project](http://roadmap.sh) and say "hi" on [Twitter](https://twitter.com/kamranahmedse).
Introduction
=================
From ba92c416a750ed9a287985d62c57cd34fefca0cc Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Wed, 17 May 2023 01:34:18 +0100
Subject: [PATCH 92/93] Add table of contents
---
readme.md | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/readme.md b/readme.md
index 4153f965..3ee4f4d4 100644
--- a/readme.md
+++ b/readme.md
@@ -16,6 +16,23 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
Check out my [other project](http://roadmap.sh) and say "hi" on [Twitter](https://twitter.com/kamranahmedse).
+
+
+|[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
=================
From 7023f30d183b6502fe8945d705f2eafdd07dcf4a Mon Sep 17 00:00:00 2001
From: fellalli
Date: Mon, 2 Dec 2024 05:54:47 +0100
Subject: [PATCH 93/93] Fix link in readme.md (#143)
* Fix link in readme.md
* Fix link in readme.md
---
readme.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/readme.md b/readme.md
index 3ee4f4d4..bacfcaa2 100644
--- a/readme.md
+++ b/readme.md
@@ -14,7 +14,7 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick
***
-Check out my [other project](http://roadmap.sh) and say "hi" on [Twitter](https://twitter.com/kamranahmedse).
+Check out my [other project](http://roadmap.sh) and say "hi" on [Twitter](https://twitter.com/kamrify).
@@ -2313,7 +2313,7 @@ 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 with any feedback [](https://twitter.com/kamranahmedse)
+- Reach out with any feedback [](https://twitter.com/kamrify)
## License