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 850317a2ff05058647edd41a271bfaa75b902b4c Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Fri, 17 Feb 2017 11:25:35 +0400 Subject: [PATCH 02/93] Minor markdown update --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index a447a254..1b989b91 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -

- -

+![](http://i.imgur.com/riLzVTY.png) ***

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 @@ -![](http://i.imgur.com/riLzVTY.png) +![Design Patterns For Humans](https://cloud.githubusercontent.com/assets/11269635/23065273/1b7e5938-f515-11e6-8dd3-d0d58de6bb9a.png) ***

@@ -564,7 +564,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. -![](http://i.imgur.com/3vgNH3p.png?2) +![With and without the bridge pattern](https://cloud.githubusercontent.com/assets/11269635/23065293/33b7aea0-f515-11e6-983f-98823c9845ee.png) 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. From 0101954dcf42b8ec8364d88463bf2c65f00763b9 Mon Sep 17 00:00:00 2001 From: Sven Luijten Date: Fri, 17 Feb 2017 16:16:53 +0100 Subject: [PATCH 11/93] Fix concatinations (#27) PHP concats with '.', not '+' --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5f9e33e0..a270d30b 100644 --- a/README.md +++ b/README.md @@ -807,7 +807,7 @@ class MilkCoffee implements Coffee { } public function getDescription() { - return $this->coffee->getDescription() + ', milk'; + return $this->coffee->getDescription() . ', milk'; } } @@ -824,7 +824,7 @@ class WhipCoffee implements Coffee { } public function getDescription() { - return $this->coffee->getDescription() + ', whip'; + return $this->coffee->getDescription() . ', whip'; } } @@ -841,7 +841,7 @@ class VanillaCoffee implements Coffee { } public function getDescription() { - return $this->coffee->getDescription() + ', vanilla'; + return $this->coffee->getDescription() . ', vanilla'; } } From ae2ca4e7f7cc234019aa8d9752f4ba451ed192f7 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Fri, 17 Feb 2017 23:21:44 +0400 Subject: [PATCH 12/93] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a270d30b..661ebdb7 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ class Carpenter implements DoorFittingExpert { } ``` -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; From e8d7fa3eb5e00750888b50a20995ccfb78243bf4 Mon Sep 17 00:00:00 2001 From: Ferri Sutanto Date: Sat, 18 Feb 2017 12:33:52 +0700 Subject: [PATCH 13/93] Wrap C letter with backtick (#33) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 661ebdb7..548ae7ef 100644 --- a/README.md +++ b/README.md @@ -1108,7 +1108,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. From f67333abf6014498662f88cccd477eb4c257d030 Mon Sep 17 00:00:00 2001 From: "Way, No" Date: Sat, 18 Feb 2017 18:34:05 +1300 Subject: [PATCH 14/93] Fixing "compuer" to "computer" (#32) A small typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 548ae7ef..414013e8 100644 --- a/README.md +++ b/README.md @@ -942,7 +942,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 From 7a307c1c589a9907dccbcb7c646a6ad5f9aad59d Mon Sep 17 00:00:00 2001 From: "Vincenzo \"vikkio88" Date: Sat, 18 Feb 2017 05:34:37 +0000 Subject: [PATCH 15/93] Fixed typo in Proxy pattern example (#31) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 414013e8..6f3e5f00 100644 --- a/README.md +++ b/README.md @@ -1080,7 +1080,7 @@ $door = new Security(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`. From 829afa218e42a48c5089c3acb3f708aa70b00809 Mon Sep 17 00:00:00 2001 From: Laurent Fourcadier Date: Sat, 18 Feb 2017 06:35:21 +0100 Subject: [PATCH 16/93] Fix typo "attatch" -> "attach" in observer pattern (#30) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6f3e5f00..de5ece57 100644 --- a/README.md +++ b/README.md @@ -1607,8 +1607,8 @@ $kaneDoe = new JobSeeker('Kane Doe'); // Create publisher and attach subscribers $jobPostings = new JobPostings(); -$jobPostings->attatch($johnDoe); -$jobPostings->attatch($janeDoe); +$jobPostings->attach($johnDoe); +$jobPostings->attach($janeDoe); // Add a new job and see if subscribers get notified $jobPostings->addJob(new JobPost('Software Engineer')); From 3a79a742c1e34eae3dc76fdd76a54ba6656517e7 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Sat, 18 Feb 2017 09:37:19 +0400 Subject: [PATCH 17/93] Minor update --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index de5ece57..d178257a 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ class CommunityExecutive implements Interviewer { Now let us create our `HiringManager` ```php - class HiringManager { +abstract class HiringManager { // Factory method abstract public function makeInterviewer() : Interviewer; @@ -153,8 +153,8 @@ Now let us create our `HiringManager` $interviewer = $this->makeInterviewer(); $interviewer->askQuestions(); } - } - ``` +} +``` Now any child can extend it and provide the required interviewer ```php class DevelopmentManager extends HiringManager { From e01468f496dd1425da5911b2bb3eba4ea89b5129 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Sat, 18 Feb 2017 09:51:05 +0400 Subject: [PATCH 18/93] Make the builder example complete --- README.md | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d178257a..e3ce1faa 100644 --- a/README.md +++ b/README.md @@ -313,16 +313,37 @@ 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 $cheeze = true; + protected $cheeze = false; protected $pepperoni = false; protected $lettuce = false; protected $tomato = false; + + public function __construct(BurgerBuilder $builder) { + $this->size = $builder->size; + $this->cheeze = $builder; + $this->pepperoni = $builder->pepperoni; + $this->lettuce = $builder->lettuce; + $this->tomato = $builder->tomato; + } +} +``` + +And then we have the builder + +```php +class BurgerBuilder { + public $size; + + public $cheeze = false; + public $pepperoni = false; + public $lettuce = false; + public $tomato = false; public function __construct(int $size) { $this->size = $size; @@ -338,14 +359,18 @@ class BurgerBuilder { return $this; } + public function addCheeze() { + $this->cheeze = true; + return $this; + } + public function addTomato() { $this->tomato = true; return $this; } public function build() : Burger { - // creational logic - return $burger; + return new Burger($this); } } ``` From 1f7b92119cf3199caa24964f92d3853083f72735 Mon Sep 17 00:00:00 2001 From: Dumindu Madunuwan Date: Sat, 18 Feb 2017 12:12:11 +0530 Subject: [PATCH 19/93] Fixing the example of Singleton pattern * We have use self::$instance instead $this->instance because $instance is a static property. * Instead of hard code the class name on return type hinting and when creating new instance, we can use self() --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e3ce1faa..483c5db5 100644 --- a/README.md +++ b/README.md @@ -475,13 +475,12 @@ final class President { // Hide the constructor } - public static function getInstance() : President { - if ($this->instance) { - return $this->instance; + public static function getInstance() : self { + if (!self::$instance) { + self::$instance = new self(); } - $this->instance = new President(); - return $this->instance; + return self::$instance; } private function __clone() { From b1d183b175204e04c983721cca1a183c8d7eb7cb Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Sat, 18 Feb 2017 11:57:33 +0400 Subject: [PATCH 20/93] Minor update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 483c5db5..7631b0d4 100644 --- a/README.md +++ b/README.md @@ -475,7 +475,7 @@ final class President { // Hide the constructor } - public static function getInstance() : self { + public static function getInstance() : President { if (!self::$instance) { self::$instance = new self(); } From ed151e836d9194152ce65b1d70df6da13a28279c Mon Sep 17 00:00:00 2001 From: Samir Moussa Date: Sat, 18 Feb 2017 13:34:29 +0000 Subject: [PATCH 21/93] Add TeaMaker object used by TeaShop object. (#37) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7631b0d4..22800961 100644 --- a/README.md +++ b/README.md @@ -1030,7 +1030,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); From 108dc734adf5a2d2446449ad6e71cd21a27deed3 Mon Sep 17 00:00:00 2001 From: Manohar Prabhu Date: Sun, 19 Feb 2017 00:45:03 +0530 Subject: [PATCH 22/93] Added the missing reference to cheeze attribute (#39) Assigning builder's cheeze attribute to burger's cheeze. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22800961..c927644c 100644 --- a/README.md +++ b/README.md @@ -326,7 +326,7 @@ class Burger { public function __construct(BurgerBuilder $builder) { $this->size = $builder->size; - $this->cheeze = $builder; + $this->cheeze = $builder->cheeze; $this->pepperoni = $builder->pepperoni; $this->lettuce = $builder->lettuce; $this->tomato = $builder->tomato; From 84aaa2ea144066e158bf3a21907e13e5e873be7f Mon Sep 17 00:00:00 2001 From: Tobias Kronthaler Date: Sat, 18 Feb 2017 20:17:43 +0100 Subject: [PATCH 23/93] Fix Parameter Type in Observer pattern (#38) Defined as JobPost , not JobPosting --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c927644c..63dc9fd9 100644 --- a/README.md +++ b/README.md @@ -1597,7 +1597,7 @@ class JobSeeker implements Observer { $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(); } From 51c8691399134682a4413a0c5748cdcbcbbbe2ac Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Sun, 19 Feb 2017 16:49:12 +0400 Subject: [PATCH 24/93] Update Web URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 63dc9fd9..a8a8d8fe 100644 --- a/README.md +++ b/README.md @@ -2025,4 +2025,4 @@ And that about wraps it up. I will continue to improve this, so you might want t - Reach out to me directly at kamranahmed.se@gmail.com or [@kamranahmedse](http://twitter.com/kamranahmedse) ## License -MIT Β© [Kamran Ahmed](https://kamranahmed.info) +MIT Β© [Kamran Ahmed](http://kamranahmed.info) From b120fe6e7c7bc3ad620bd1a3bcc6ff80180c575d Mon Sep 17 00:00:00 2001 From: Sobolev Nikita Date: Sun, 19 Feb 2017 21:45:46 +0300 Subject: [PATCH 25/93] Fixes typo in the README.md (#41) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a8a8d8fe..69b82fa4 100644 --- a/README.md +++ b/README.md @@ -1368,7 +1368,7 @@ class StationList implements Countable, Iterator { $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; From 03bcbc361b07d1331403fb9314f079018c65cd3e Mon Sep 17 00:00:00 2001 From: Alex Nastase Date: Mon, 20 Feb 2017 04:49:07 +0200 Subject: [PATCH 26/93] Fix typo and extra semicolons. (#42) --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 69b82fa4..a4327f7d 100644 --- a/README.md +++ b/README.md @@ -319,14 +319,14 @@ The sane alternative is to use the builder pattern. First of all we have our bur class Burger { protected $size; - protected $cheeze = false; + protected $cheese = false; protected $pepperoni = false; protected $lettuce = false; protected $tomato = false; public function __construct(BurgerBuilder $builder) { $this->size = $builder->size; - $this->cheeze = $builder->cheeze; + $this->cheese = $builder->cheese; $this->pepperoni = $builder->pepperoni; $this->lettuce = $builder->lettuce; $this->tomato = $builder->tomato; @@ -340,7 +340,7 @@ And then we have the builder class BurgerBuilder { public $size; - public $cheeze = false; + public $cheese = false; public $pepperoni = false; public $lettuce = false; public $tomato = false; @@ -359,8 +359,8 @@ class BurgerBuilder { return $this; } - public function addCheeze() { - $this->cheeze = true; + public function addCheese() { + $this->cheese = true; return $this; } @@ -378,9 +378,9 @@ And then it can be used as: ```php $burger = (new BurgerBuilder(14)) - ->addPepperoni(); - ->addLettuce(); - ->addTomato(); + ->addPepperoni() + ->addLettuce() + ->addTomato() ->build(); ``` From 7a23017345b48038447fa8ce5c06798af7dfc31c Mon Sep 17 00:00:00 2001 From: Adnan Ahmed Date: Mon, 20 Feb 2017 12:01:49 +0400 Subject: [PATCH 27/93] Added missing semicolon (#44) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a4327f7d..4d2c9dff 100644 --- a/README.md +++ b/README.md @@ -1091,7 +1091,7 @@ class Security { } public function authenticate($password) { - return $password === '$ecr@t' + return $password === '$ecr@t'; } public function close() { From 982e23a38d18f0bfe677d552d5012b5a57ccaeea Mon Sep 17 00:00:00 2001 From: Martin Madsen Date: Tue, 21 Feb 2017 14:04:03 +1000 Subject: [PATCH 28/93] Minor grammatical fixes (#46) --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4d2c9dff..fed0c768 100644 --- a/README.md +++ b/README.md @@ -1646,10 +1646,10 @@ $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. @@ -1832,18 +1832,18 @@ $sorter->sort($dataset); // 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. +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 @@ -1924,7 +1924,7 @@ Real world example > 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. From ca5d8d9e113ec381088feab8995f7db0ec937a4b Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Tue, 21 Feb 2017 13:17:26 +0400 Subject: [PATCH 29/93] Fix issue#47 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fed0c768..dadbccfe 100644 --- a/README.md +++ b/README.md @@ -1313,8 +1313,8 @@ 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! From 82af66ee26cde3da763a7f58c88ce4de833da1b0 Mon Sep 17 00:00:00 2001 From: Joris Neuteboom Date: Tue, 21 Feb 2017 15:07:32 +0100 Subject: [PATCH 30/93] Fixed the example for Chain of Responsibility (#49) Now it will actual give the same result as the example snippet before it was just returning: Paid 259 using Bank --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index dadbccfe..0c7a4cb9 100644 --- a/README.md +++ b/README.md @@ -1156,7 +1156,7 @@ abstract class Account { public function pay(float $amountToPay) { if ($this->canPay($amountToPay)) { - echo sprintf('Paid %s using %s' . PHP_EOL, $amount, get_called_class()); + echo sprintf('Paid %s using %s' . PHP_EOL, $amountToPay, get_called_class()); } else if ($this->successor) { echo sprintf('Cannot pay using %s. Proceeding ..' . PHP_EOL, get_called_class()); $this->successor->pay($amountToPay); @@ -1166,7 +1166,7 @@ abstract class Account { } public function canPay($amount) : bool { - return $this->balance <= $amount; + return $this->balance >= $amount; } } @@ -1174,7 +1174,7 @@ class Bank extends Account { protected $balance; public function __construct(float $balance) { - $this->$balance = $balance; + $this->balance = $balance; } } @@ -1182,7 +1182,7 @@ class Paypal extends Account { protected $balance; public function __construct(float $balance) { - $this->$balance = $balance; + $this->balance = $balance; } } @@ -1190,7 +1190,7 @@ class Bitcoin extends Account { protected $balance; public function __construct(float $balance) { - $this->$balance = $balance; + $this->balance = $balance; } } ``` From 71f45c7de28ed47aeb314aedbc69abef336bca48 Mon Sep 17 00:00:00 2001 From: Alois Date: Tue, 21 Feb 2017 15:07:49 +0100 Subject: [PATCH 31/93] Remove superflous ` (#48) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c7a4cb9..4c737fb6 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ class WoodenDoor implements Door { return $this->height; } } -```` +``` Then we have our door factory that makes the door and returns it ```php class DoorFactory { From 518e7ab24293255ed731f48f23d875f339a7563e Mon Sep 17 00:00:00 2001 From: Povilas Susinskas Date: Tue, 21 Feb 2017 16:16:58 +0200 Subject: [PATCH 32/93] Improve SingletonPattern (#50) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 4c737fb6..91dad31a 100644 --- a/README.md +++ b/README.md @@ -486,6 +486,10 @@ final class President { private function __clone() { // Disable cloning } + + private function __wakeup() { + // Disable unserialize + } } ``` Then in order to use From d72d4933f5a00bd89de3bb21666ebcce90d015ee Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Tue, 21 Feb 2017 18:34:37 +0400 Subject: [PATCH 33/93] Fixes #51 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 91dad31a..476f0eef 100644 --- a/README.md +++ b/README.md @@ -1321,8 +1321,8 @@ $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. From 4b807b83129e2b751c70dbfaeb26e79ff7052529 Mon Sep 17 00:00:00 2001 From: Mohammed Ismail Ansari Date: Tue, 21 Feb 2017 22:32:09 +0530 Subject: [PATCH 34/93] add a missed word in introduction (#52) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 476f0eef..d6f36b71 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 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 From e593332ac236ce5cba579fc19baa22450edfa747 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Tue, 21 Feb 2017 21:21:43 +0400 Subject: [PATCH 35/93] Itsy bitsy update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6f36b71..62af0b30 100644 --- a/README.md +++ b/README.md @@ -2026,7 +2026,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 to me directly at kamranahmed.se@gmail.com or [@kamranahmedse](http://twitter.com/kamranahmedse) +- Reach out to me directly at kamranahmed.se@gmail.com or on twitter [@kamranahmedse](http://twitter.com/kamranahmedse) ## License MIT Β© [Kamran Ahmed](http://kamranahmed.info) From a4bde4fb370bdfa6f982333aa7037df171b0293c Mon Sep 17 00:00:00 2001 From: Galdor Date: Tue, 21 Feb 2017 22:02:07 +0100 Subject: [PATCH 36/93] Fix typo in template method (#55) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62af0b30..eb955a66 100644 --- a/README.md +++ b/README.md @@ -1951,7 +1951,7 @@ abstract class Builder { public abstract function test(); public abstract function lint(); - public abstract function build(); + public abstract function assemble(); public abstract function deploy(); } ``` From 187ca31b5cc9ece24bbb48ee9f98f0f3d251dc4e Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Wed, 22 Feb 2017 08:23:24 +0400 Subject: [PATCH 37/93] Add language note --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index eb955a66..b9fa0c87 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Types of Design Patterns * [Structural](#structural-design-patterns) * [Behavioral](#behavioral-design-patterns) +> β„Ή Note that the code samples below are in PHP-7. However the support for other languages is under way! Creational Design Patterns ========================== From 231768979b21008341e114ed92235f3c9639b9dc Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Wed, 22 Feb 2017 08:26:44 +0400 Subject: [PATCH 38/93] Add information note --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b9fa0c87..1573ab78 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Types of Design Patterns * [Structural](#structural-design-patterns) * [Behavioral](#behavioral-design-patterns) -> β„Ή Note that the code samples below are in PHP-7. However the support for other languages is under way! +> β„Ή Note that the code samples below are in PHP-7. However the **support for other languages is underway**. But this shouldn't stop you because the concepts are same anyways. Creational Design Patterns ========================== From 48050f08c83d600fd44684e69982c1eb1ea505da Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Wed, 22 Feb 2017 08:28:09 +0400 Subject: [PATCH 39/93] Placement for note --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1573ab78..74fff357 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ Wikipedia describes them as - 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. +> β„Ή Note that the code samples below are in PHP-7. However the **support for other languages is underway**. But this shouldn't stop you because the concepts are same anyways. + Types of Design Patterns ----------------- @@ -33,8 +35,6 @@ Types of Design Patterns * [Structural](#structural-design-patterns) * [Behavioral](#behavioral-design-patterns) -> β„Ή Note that the code samples below are in PHP-7. However the **support for other languages is underway**. But this shouldn't stop you because the concepts are same anyways. - Creational Design Patterns ========================== From e97e31b04a89d2a9b6898ad30385b73dce73e500 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Wed, 22 Feb 2017 08:29:04 +0400 Subject: [PATCH 40/93] Rephrase the note --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 74fff357..bea87166 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Wikipedia describes them as - 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. -> β„Ή Note that the code samples below are in PHP-7. However the **support for other languages is underway**. But this shouldn't stop you because the concepts are same anyways. +> 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**. Types of Design Patterns ----------------- From b61ac00fa59671caee204c845e16c47eb6295135 Mon Sep 17 00:00:00 2001 From: Rougin Gutib Date: Thu, 23 Feb 2017 11:44:46 +0800 Subject: [PATCH 41/93] Formatting changes * Add new line at "Programmatic Example" in Facade * Formatting changes --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index bea87166..11a8e61f 100644 --- a/README.md +++ b/README.md @@ -909,6 +909,7 @@ 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 @@ -987,6 +988,7 @@ 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 @@ -1060,6 +1062,7 @@ 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 @@ -1341,6 +1344,7 @@ 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 From b75365b4f69222b160c57bce5c11a32c7422fefa Mon Sep 17 00:00:00 2001 From: Ramon Fritsch Date: Sat, 25 Feb 2017 00:03:54 -0800 Subject: [PATCH 42/93] Minor example update (#65) `$kaneDoe` variable is not being used in the example --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 11a8e61f..138c3f16 100644 --- a/README.md +++ b/README.md @@ -1637,7 +1637,6 @@ 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(); From b9a53a87a4026cb0b8e76feba72a91ecfcdf4f45 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Mon, 27 Feb 2017 07:39:23 +0400 Subject: [PATCH 43/93] Minor fix - Iterator pattern example --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 138c3f16..f515c4bd 100644 --- a/README.md +++ b/README.md @@ -1414,16 +1414,16 @@ 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 From 5cf37f78ec96ed764ee98fa34f240f74f5470327 Mon Sep 17 00:00:00 2001 From: Vadim Date: Tue, 28 Feb 2017 20:43:59 +0700 Subject: [PATCH 44/93] State - class names fix (#70) * State - class names fix * State - class names fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f515c4bd..a365525b 100644 --- a/README.md +++ b/README.md @@ -1902,12 +1902,12 @@ $editor = new TextEditor(new Default()); $editor->type('First line'); -$editor->setState(new UpperCaseState()); +$editor->setState(new UpperCase()); $editor->type('Second line'); $editor->type('Third line'); -$editor->setState(new LowerCaseState()); +$editor->setState(new LowerCase()); $editor->type('Fourth line'); $editor->type('Fifth line'); From 318d0fb69cefde1de1279a990a52f07541fc3197 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Wed, 1 Mar 2017 16:26:36 +0400 Subject: [PATCH 45/93] Minor update --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a365525b..bfcea2c7 100644 --- a/README.md +++ b/README.md @@ -1929,6 +1929,7 @@ Real world example > - 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 From a84d74043e7815ddfe70332038be249269548f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire?= Date: Thu, 2 Mar 2017 11:52:57 +0100 Subject: [PATCH 46/93] Just minor cs fix on returning types (#64) * minor cs fixing * PSR2 --- README.md | 1040 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 640 insertions(+), 400 deletions(-) diff --git a/README.md b/README.md index bfcea2c7..fbd15d41 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,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. +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 @@ ![Design Patterns For Humans](https://cloud.githubusercontent.com/assets/11269635/23065273/1b7e5938-f515-11e6-8dd3-d0d58de6bb9a.png) *** +

πŸŽ‰ 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!

Also follow me on twitter @kamranahmedse to keep track of what I am upto.

*** From 3bc5b230f30b762ea377f66c7d5d7ed3f33403bf Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Thu, 20 Apr 2017 22:40:14 +0400 Subject: [PATCH 57/93] Removing twitter handle --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 97a5c21a..ae1c6245 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 *** -

Do you like startups or aspire to be a founder?
We are releasing Hugobots soon. Make sure to subscribe!

Also follow me on twitter @kamranahmedse to keep track of what I am upto.

+

Do you like startups or aspire to be a founder?
We are releasing Hugobots soon. Make sure to subscribe!

*** From 2df95ade18842320cf619702d99608fcc8984723 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Fri, 21 Apr 2017 11:47:26 +0400 Subject: [PATCH 58/93] Minor update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae1c6245..e39fc08a 100644 --- a/README.md +++ b/README.md @@ -2283,7 +2283,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 to me directly at kamranahmed.se@gmail.com or on twitter [@kamranahmedse](http://twitter.com/kamranahmedse) +- Reach out to me directly at kamranahmed.se@gmail.com or [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamranahmedse.svg?style=social&label=Follow%20%40kamranahmedse)](https://twitter.com/kamranahmedse) ## License MIT Β© [Kamran Ahmed](http://kamranahmed.info) From 6d8a12c96594928eded9ffc62833a786b55f057b Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Sun, 7 May 2017 20:54:56 +0400 Subject: [PATCH 59/93] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e39fc08a..f074cbfe 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 *** -

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!

*** From 99f1d72452016efc539e5c6309fbbada83e35adb Mon Sep 17 00:00:00 2001 From: Lost Koder Date: Thu, 6 Jul 2017 06:18:55 +0430 Subject: [PATCH 61/93] [Factory Method] Changed method accessor from public to protected for encapsulation purposes (#93) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dcd1288c..a0071b36 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ abstract class HiringManager { // Factory method - abstract public function makeInterviewer(): Interviewer; + abstract protected function makeInterviewer(): Interviewer; public function takeInterview() { @@ -182,7 +182,7 @@ Now any child can extend it and provide the required interviewer ```php class DevelopmentManager extends HiringManager { - public function makeInterviewer(): Interviewer + protected function makeInterviewer(): Interviewer { return new Developer(); } @@ -190,7 +190,7 @@ class DevelopmentManager extends HiringManager class MarketingManager extends HiringManager { - public function makeInterviewer(): Interviewer + protected function makeInterviewer(): Interviewer { return new CommunityExecutive(); } From f05b58af35884ae4855e9b470b246cf3bc8ec7fe Mon Sep 17 00:00:00 2001 From: Dmitry Kuznetsov Date: Thu, 6 Jul 2017 12:47:49 +0300 Subject: [PATCH 62/93] Add $roles to composite pattern (#86) composite pattern: added protected variable $roles in two classes implementing the class Employee --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a0071b36..1d7a8935 100644 --- a/README.md +++ b/README.md @@ -792,7 +792,8 @@ class Developer implements Employee { protected $salary; protected $name; - + protected $roles; + public function __construct(string $name, float $salary) { $this->name = $name; @@ -824,6 +825,7 @@ class Designer implements Employee { protected $salary; protected $name; + protected $roles; public function __construct(string $name, float $salary) { From b9a3c21f638d797a1554b09070370a0901c0e637 Mon Sep 17 00:00:00 2001 From: Ting-Chun Sun Date: Thu, 6 Jul 2017 02:48:54 -0700 Subject: [PATCH 63/93] fix a typo in composite method (#84) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d7a8935..d99c1e9e 100644 --- a/README.md +++ b/README.md @@ -892,7 +892,7 @@ $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 From efb2408dc1de4ba2c8ae10a4edc24fb04ddc6974 Mon Sep 17 00:00:00 2001 From: Tito Esteves Date: Sat, 29 Jul 2017 23:25:04 -0700 Subject: [PATCH 64/93] Fix grammar in sentence (#96) * fix grammar in sentence * fix grammar in sentence --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d99c1e9e..4b9622de 100644 --- a/README.md +++ b/README.md @@ -522,7 +522,7 @@ In plain words 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** @@ -1388,7 +1388,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 From c39f036d09e26d18dfa0b51b67a911dc63be0a78 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Mon, 18 Sep 2017 15:32:15 +0400 Subject: [PATCH 65/93] Add badges --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4b9622de..8e2d6c3e 100644 --- a/README.md +++ b/README.md @@ -2285,7 +2285,9 @@ 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 [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamranahmedse.svg?style=social&label=Follow%20%40kamranahmedse)](https://twitter.com/kamranahmedse) -## License -MIT Β© [Kamran Ahmed](http://kamranahmed.info) +--- + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](http://paypal.me/kamranahmedse) +[![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamranahmedse.svg?style=social&label=Follow%20%40kamranahmedse)](https://twitter.com/kamranahmedse) From 053158116aa54bde3779841ef75976415adf36b1 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Tue, 19 Sep 2017 14:56:13 +0400 Subject: [PATCH 66/93] =?UTF-8?q?Add=20paypal=20link=20=F0=9F=99=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8e2d6c3e..72503502 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?
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 [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamranahmedse.svg?style=social&label=Follow%20%40kamranahmedse)](https://twitter.com/kamranahmedse) --- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](http://paypal.me/kamranahmedse) -[![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamranahmedse.svg?style=social&label=Follow%20%40kamranahmedse)](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 [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamranahmedse.svg?style=social&label=Follow%20%40kamranahmedse)](https://twitter.com/kamranahmedse) ---- +## License [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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 -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](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 [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamranahmedse.svg?style=social&label=Follow%20%40kamranahmedse)](https://twitter.com/kamranahmedse) -## License +## Sponsored By + +- [Highig - Think and its done](http://highig.com/) + +## License [![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](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!

+

I recently started a weekly booklet on Modern Frontend Development
ES Guy – Weekly delight to cure your JS fatigue

*** +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.

- *** -

I recently started a weekly booklet on Modern Frontend Development
ES Guy – Weekly delight to cure your JS fatigue

+

πŸ‘‹ You might be interested in ES Guy – Weekly booklet on Frontend Development
Read the details and Subscribe here

*** + Check out my [blog](http://kamranahmed.info) and say "hi" on [Twitter](https://twitter.com/kamranahmedse). πŸš€ Introduction From da93f06d81ddf32e72e7a7ae1748f6f0eb1d946a Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Fri, 13 Apr 2018 12:28:09 +0200 Subject: [PATCH 77/93] Minor Rephrase --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b8ed31c7..c5cfd0ff 100644 --- a/README.md +++ b/README.md @@ -1816,7 +1816,7 @@ 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 = []; @@ -1845,7 +1845,7 @@ $johnDoe = new JobSeeker('John Doe'); $janeDoe = new JobSeeker('Jane Doe'); // Create publisher and attach subscribers -$jobPostings = new JobPostings(); +$jobPostings = new EmploymentAgency(); $jobPostings->attach($johnDoe); $jobPostings->attach($janeDoe); From f73526255a8f6e7c722496782b2d006edb8316d7 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Fri, 13 Apr 2018 12:32:23 +0200 Subject: [PATCH 78/93] Update adapter example --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c5cfd0ff..bb4352ee 100644 --- a/README.md +++ b/README.md @@ -627,6 +627,7 @@ class Hunter { public function hunt(Lion $lion) { + $lion->roar(); } } ``` From 6485f2be895de09b42120c673b45eba5232267dc Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Sat, 5 May 2018 23:02:40 +0200 Subject: [PATCH 79/93] Update banner --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb4352ee..7f4a984c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A topic that can easily make anyone's mind wobble. Here I try to make them stick *** -

πŸ‘‹ You might be interested in ES Guy – Weekly booklet on Frontend Development
Read the details and Subscribe here

+

πŸ‘‹ You might be interested in ES Guy – Weekly booklet on Full-Stack Development
Read the details and Subscribe here

*** 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 *** -

πŸ‘‹ You might be interested in ES Guy – Weekly booklet on Full-Stack Development
Read the details and Subscribe here

- -*** - 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://img.shields.io/badge/paypal-buy%20me%20a%20coffee-green.svg?style=for-the-badge)](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://img.shields.io/badge/paypal-buy%20me%20a%20coffee-green.svg?style=for-the-badge)](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 [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamranahmedse.svg?style=social&label=Follow%20%40kamranahmedse)](https://twitter.com/kamranahmedse) -## Sponsored By - -- [Highig - Think and its done](http://highig.com/) - ## License [![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](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 @@ -![Design Patterns For Humans](https://cloud.githubusercontent.com/assets/11269635/23065273/1b7e5938-f515-11e6-8dd3-d0d58de6bb9a.png) +
+

+ +

+
*** 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 @@

- +

-
*** @@ -10,12 +9,12 @@ πŸŽ‰ 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. +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 [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamranahmedse.svg?style=social&label=Follow%20%40kamranahmedse)](https://twitter.com/kamranahmedse) +- Reach out with any feedback [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/kamrify.svg?style=social&label=Follow%20%40kamrify)](https://twitter.com/kamrify) ## License