├── README.md ├── behavioral ├── chain-of-resposibility │ └── readme.md ├── command │ └── readme.md ├── readme.md ├── state │ └── readme.md └── template │ └── readme.md ├── creational ├── builder │ ├── builder-pattern.png │ ├── multiple.md │ └── readme.md ├── factory │ ├── factory-pattern-simple.png │ └── readme.md ├── prototype │ └── readme.md ├── readme.md └── singleton │ ├── readme.md │ └── singleton-pattern.png ├── structural ├── adapter │ └── readme.md ├── decorator │ └── readme.md ├── facades │ └── readme.md ├── proxy │ └── readme.md └── readme.md └── the-solid-principle └── readme.md /README.md: -------------------------------------------------------------------------------- 1 | # What is design pattern ? 2 | 3 | Design pattern is a description/guidline for solve occuring problem when software development. 4 | 5 | The pattern is not a specific piece of code, but a general `concept/strategy` for solving a particular problem 6 | 7 | * `Solutions to problems` 8 | 9 | 10 | # Why use design pattern ? 11 | 12 | * Understandable 13 | * Adaptable 14 | * Extenable 15 | * Debugable 16 | * Mainatable 17 | 18 | # Usage of design pattern 19 | 20 | * Common platform for all 21 | * Best practise 22 | 23 | # Categories of design pattern 24 | 25 | * [Creational](https://github.com/code4mk/software-design-pattern/tree/main/creational) 26 | * [Structural](https://github.com/code4mk/software-design-pattern/tree/main/structural) 27 | * [Behavioral](https://github.com/code4mk/software-design-pattern/tree/main/behavioral) 28 | 29 | ~ According to Gang of four's - 23 type of design patterns. 30 | 31 | 32 | # Resources 33 | 34 | * https://github.com/kamranahmedse/design-patterns-for-humans#introduction 35 | * https://sourcemaking.com/design_patterns 36 | * https://www.tutorialspoint.com/design_pattern/design_pattern_overview.htm 37 | * https://www.freecodecamp.org/news/the-basic-design-patterns-all-developers-need-to-know/ 38 | * https://www.script-tutorials.com/design-patterns-in-php/ 39 | * https://www.packtpub.com/product/laravel-design-patterns-and-best-practices/9781783287987 40 | * https://www.youtube.com/watch?v=pTB0EiLXUC8&pbjreload=101 41 | 42 | # laravel 43 | 44 | * https://www.larashout.com/how-to-use-repository-pattern-in-laravel 45 | -------------------------------------------------------------------------------- /behavioral/chain-of-resposibility/readme.md: -------------------------------------------------------------------------------- 1 | # Chain pattern 2 | 3 | * middleware ( handler->handler->handler) 4 | 5 | 6 | # resources 7 | 8 | * [sitepoint](https://www.sitepoint.com/introduction-to-chain-of-responsibility/) 9 | * [inanzzz](http://www.inanzzz.com/index.php/post/elqr/chain-of-responsibility-design-pattern-example-with-php) 10 | * [jkapuscik2/design-patterns-php](https://github.com/jkapuscik2/design-patterns-php/tree/master/behavioral/ChainOfResponsibility) 11 | * [laravel-chain-of-responsibility-example](https://github.com/nkusibojoski/laravel-chain-of-responsibility-example/tree/master/app/Helpers) 12 | -------------------------------------------------------------------------------- /behavioral/command/readme.md: -------------------------------------------------------------------------------- 1 | # command pattern 2 | 3 | * https://webmobtuts.com/backend-development/command-design-pattern-in-php/ 4 | * https://code.tutsplus.com/tutorials/design-patterns-the-command-pattern--cms-22942 5 | -------------------------------------------------------------------------------- /behavioral/readme.md: -------------------------------------------------------------------------------- 1 | # Behavioral 2 | 3 | How indivisual object works for common goal or problem. 4 | 5 | In software engineering, behavioral design patterns are design patterns that identify common communication patterns between object. 6 | 7 | # 10 pattern 8 | 9 | 1. command 10 | 2. state 11 | 3. template 12 | 4. chain of resposibility 13 | 5. visitor 14 | 6. observer 15 | 7. memento 16 | 8. mediator 17 | 9. iterator 18 | 10. strategy 19 | -------------------------------------------------------------------------------- /behavioral/state/readme.md: -------------------------------------------------------------------------------- 1 | # state pattern 2 | 3 | * 4 | 5 | 6 | # resources 7 | 8 | * [jkapuscik2/design-patterns-php](https://github.com/jkapuscik2/design-patterns-php/blob/master/behavioral/State) 9 | -------------------------------------------------------------------------------- /behavioral/template/readme.md: -------------------------------------------------------------------------------- 1 | # Template design pattern 2 | 3 | * template is a fixed preset format. 4 | 5 | 6 | ~ sublcass / super class 7 | 8 | * https://stackoverflow.com/questions/5863682/what-is-a-subclass 9 | 10 | # resources 11 | 12 | * [webdevetc](https://webdevetc.com/blog/template-method-design-pattern-explained-php/) 13 | * [o'reilly](https://www.oreilly.com/library/view/learning-php-design/9781449344900/ch09.html) 14 | * [tutorial point](https://www.tutorialspoint.com/design_pattern/template_pattern.htm) 15 | * [geeksforgeeks](https://www.geeksforgeeks.org/template-method-design-pattern/) 16 | * [dzone](https://dzone.com/articles/using-template-method-design-pattern-in-java) 17 | * [darek Banas](https://www.youtube.com/watch?v=aR1B8MlwbRI) 18 | * [jkapuscik2/design-patterns-php](https://github.com/jkapuscik2/design-patterns-php/tree/master/behavioral/TemplateMethod) *** 19 | * [domnikl/DesignPatternsPHP](https://github.com/domnikl/DesignPatternsPHP/tree/main/Behavioral/TemplateMethod) *** 20 | -------------------------------------------------------------------------------- /creational/builder/builder-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code4mk/software-design-pattern/755de56edb0da17a0e3560ff31d9b12494d2d2e0/creational/builder/builder-pattern.png -------------------------------------------------------------------------------- /creational/builder/multiple.md: -------------------------------------------------------------------------------- 1 | * create a complex object step by step. 2 | 3 | ```php 4 | // Builder design pattern 5 | // code4mk 6 | 7 | phone = new SamsungPhone(); 39 | $this->options = $options; 40 | 41 | } 42 | 43 | public function addCamera() 44 | { 45 | $this->phone->camera = $this->options['camera']; 46 | } 47 | 48 | public function addRam() 49 | { 50 | $this->phone->ram = $this->options['ram']; 51 | } 52 | 53 | public function getProduct() 54 | { 55 | return $this->phone; 56 | } 57 | } 58 | 59 | class RedmiPhoneBuilder implements SmartPhoneBuilder 60 | { 61 | private $phone; 62 | private $optinos; 63 | public function __construct($options) 64 | { 65 | $this->phone = new RedmiPhone(); 66 | $this->options = $options; 67 | 68 | } 69 | 70 | public function addCamera() 71 | { 72 | $this->phone->camera = $this->options['camera']; 73 | } 74 | 75 | public function addRam() 76 | { 77 | $this->phone->ram = $this->options['ram']; 78 | } 79 | 80 | public function getProduct() 81 | { 82 | return $this->phone; 83 | } 84 | } 85 | 86 | class SmartPhoneCreator 87 | { 88 | public function build(SmartphoneBuilder $builder) 89 | { 90 | $builder->addCamera(); 91 | $builder->addRam(); 92 | return $builder->getProduct(); 93 | } 94 | } 95 | 96 | $creator = new SmartPhoneCreator(); 97 | $samsungBuilder = new SamsungPhoneBuilder(['camera' => '64', 'ram' => '16']); 98 | $redmiBuilder = new RedmiPhoneBuilder(['camera' => '12','ram' => '64']); 99 | 100 | print_r ($creator->build($samsungBuilder)); 101 | print_r ($creator->build($redmiBuilder)); 102 | ``` 103 | ![](https://refactoring.guru/images/patterns/content/builder/builder-en.png) 104 | 105 | # resources 106 | 107 | * https://designpatternsphp.readthedocs.io/en/latest/Creational/Builder/README.html 108 | * https://refactoring.guru/design-patterns/builder 109 | * https://gist.github.com/aliselcuk/59e702e55d26de15c7fa2ef7907373c2 110 | * https://gist.github.com/firefoxrebo/f78ab3c352b77279c94e208570eaf187 111 | -------------------------------------------------------------------------------- /creational/builder/readme.md: -------------------------------------------------------------------------------- 1 | * create a complex object step by step. 2 | 3 | ```php 4 | // Builder design pattern 5 | // code4mk 6 | 7 | class SmartPhone 8 | { 9 | public $ram; 10 | public $camera; 11 | } 12 | 13 | class SamsungPhone extends SmartPhone 14 | { 15 | 16 | } 17 | 18 | interface SmartPhoneBuilder 19 | { 20 | 21 | public function addRam(); 22 | 23 | public function addCamera(); 24 | 25 | public function getPhoneDetails(); 26 | } 27 | 28 | class SamsungPhoneBuilder implements SmartPhoneBuilder 29 | { 30 | private $phone; 31 | private $options; 32 | 33 | public function __construct(array $options) 34 | { 35 | $this->phone = new SamsungPhone(); 36 | $this->options = $options; 37 | } 38 | public function addRam() 39 | { 40 | $this->phone->ram = $this->options['ram']; 41 | } 42 | 43 | public function addCamera() 44 | { 45 | $this->phone->camera = $this->options['camera']; 46 | } 47 | 48 | public function getPhoneDetails() 49 | { 50 | return $this->phone; 51 | } 52 | } 53 | 54 | class SmartPhoneCreator 55 | { 56 | public function build(SmartPhoneBuilder $builder) 57 | { 58 | $builder->addRam(); 59 | $builder->addCamera(); 60 | return $builder->getPhoneDetails(); 61 | } 62 | } 63 | 64 | $samsungPhone = new SamsungPhoneBuilder(['ram' => '16gb', 'camera' => '64pixel']); 65 | $samsungSmartPhoneCreate = new SmartPhoneCreator(); 66 | print_r ($samsungSmartPhoneCreate->build($samsungPhone)); 67 | ``` 68 | 69 | # image 70 | 71 | ![builder pattern](builder-pattern.png) 72 | 73 | ![](https://refactoring.guru/images/patterns/content/builder/builder-en.png) 74 | 75 | # resources 76 | 77 | * https://designpatternsphp.readthedocs.io/en/latest/Creational/Builder/README.html 78 | * https://refactoring.guru/design-patterns/builder 79 | * https://gist.github.com/aliselcuk/59e702e55d26de15c7fa2ef7907373c2 80 | * https://gist.github.com/firefoxrebo/f78ab3c352b77279c94e208570eaf187 81 | -------------------------------------------------------------------------------- /creational/factory/factory-pattern-simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code4mk/software-design-pattern/755de56edb0da17a0e3560ff31d9b12494d2d2e0/creational/factory/factory-pattern-simple.png -------------------------------------------------------------------------------- /creational/factory/readme.md: -------------------------------------------------------------------------------- 1 | # Factory pattern 2 | 3 | Factory pattern create instance for others. 4 | 5 | Factory design pattern works like a factory in the real world in that it creates something for others to use. In the context of OOP, it helps in creating and instantiating objects. 6 | 7 | # Factory type 8 | 9 | * simple factory 10 | * abtract factory 11 | * factory method 12 | 13 | # simple factory 14 | 15 | ![](factory-pattern-simple.png) 16 | 17 | # factory method 18 | 19 | ```php 20 | class DBFactory 21 | { 22 | private $driver; 23 | 24 | public function setDriver($driver) 25 | { 26 | $this->driver = $driver 27 | } 28 | 29 | public function makeDB($host, $dbname, $user, $pass) 30 | { 31 | $db; 32 | if ($this->driver == 'mysql') { 33 | $db = new Mysql(); 34 | }elseif ($this->driver == 'postgre') { 35 | $db = new Postgre(); 36 | }else{ 37 | $db = new Sqlite(); 38 | } 39 | 40 | $db->setHost($host); 41 | $db->setDB($dbname); 42 | $db->setUserName($user); 43 | $db->setPassword($pass); 44 | $db->connect(); 45 | 46 | return $db; 47 | } 48 | } 49 | 50 | $dbFactory = new DBFactory; 51 | $dbFactory->setDriver('mysql')); 52 | $DB = $dbFactory->makeDB("host", "db", "user", "pwd"); 53 | ``` 54 | # Abstract factory 55 | 56 | ```php 57 | abstract class Employee 58 | { 59 | abstract public function info(); 60 | 61 | public function getName() 62 | { 63 | return 'name: ' . $this->info()->name(); 64 | } 65 | } 66 | 67 | class HrInfo 68 | { 69 | public function name() 70 | { 71 | return 'kamal'; 72 | } 73 | } 74 | 75 | class Hr extends Employee 76 | { 77 | public function info() 78 | { 79 | return new HrInfo(); 80 | } 81 | } 82 | 83 | $hr = new Hr(); 84 | print_r($hr->getName()); 85 | // kamal 86 | ``` 87 | 88 | # resources 89 | * https://gist.github.com/oktapodi/6ea734dbb945b69f9fcc `simple factory` 90 | * https://refactoring.guru/design-patterns/factory-method/php/example#example-1 `abstract` 91 | * https://codeinphp.github.io/post/factory-design-pattern/ `factory method` 92 | * https://github.com/domnikl/DesignPatternsPHP/tree/main/Creational/SimpleFactory 93 | * https://webmobtuts.com/backend-development/creating-classes-with-php-factory-abstract-factory-simple-and-static-factory-patterns/ 94 | * https://stackoverflow.com/questions/4719822/factory-abstract-factory-confusion 95 | 96 | * https://kousiknath.medium.com/design-patterns-different-approaches-to-use-factory-pattern-to-choose-objects-dynamically-at-run-71449bceecef *** 97 | -------------------------------------------------------------------------------- /creational/prototype/readme.md: -------------------------------------------------------------------------------- 1 | # prototype 2 | * clone a object 3 | 4 | ```php 5 | class Sheep 6 | { 7 | protected $name; 8 | protected $category; 9 | 10 | public function __construct(string $name, string $category = 'Mountain Sheep') 11 | { 12 | $this->name = $name; 13 | $this->category = $category; 14 | } 15 | 16 | public function setName(string $name) 17 | { 18 | $this->name = $name; 19 | } 20 | 21 | public function getName() 22 | { 23 | return $this->name; 24 | } 25 | 26 | public function setCategory(string $category) 27 | { 28 | $this->category = $category; 29 | } 30 | 31 | public function getCategory() 32 | { 33 | return $this->category; 34 | } 35 | } 36 | ``` 37 | Then it can be cloned like below 38 | 39 | ```php 40 | $original = new Sheep('Jolly'); 41 | echo $original->getName(); // Jolly 42 | echo $original->getCategory(); // Mountain Sheep 43 | 44 | // Clone and modify what is required 45 | $cloned = clone $original; 46 | $cloned->setName('Dolly'); 47 | echo $cloned->getName(); // Dolly 48 | echo $cloned->getCategory(); // Mountain sheep 49 | ``` 50 | # source 51 | 52 | * [kamranahmedse/design-patterns-for-humans](https://github.com/kamranahmedse/design-patterns-for-humans#-prototype) 53 | -------------------------------------------------------------------------------- /creational/readme.md: -------------------------------------------------------------------------------- 1 | # creational 2 | 3 | * creational patterns related for creation or cloning new object. 4 | 5 | # 6 design patterns 6 | 7 | * [singleton](https://github.com/code4mk/software-design-pattern/tree/main/creational/singleton) - single instance 8 | * [factory (3)](https://github.com/code4mk/software-design-pattern/tree/main/creational/factory) - create instance for others 9 | * [simple factory](https://github.com/code4mk/software-design-pattern/tree/main/creational/factory#simple-factory) 10 | * [factory method](https://github.com/code4mk/software-design-pattern/tree/main/creational/factory#factory-method) 11 | * [abstract factory](https://github.com/code4mk/software-design-pattern/tree/main/creational/factory#abstract-factory) 12 | * [builder](https://github.com/code4mk/software-design-pattern/tree/main/creational/builder) - object create step by step 13 | * [prototype](https://github.com/code4mk/software-design-pattern/tree/main/creational/prototype) - clone a object 14 | -------------------------------------------------------------------------------- /creational/singleton/readme.md: -------------------------------------------------------------------------------- 1 | # Singleton Design pattern 2 | 3 | Singleton design pattern create a single object of a class. 4 | 5 | 6 | ~ 7 | 8 | * class oriented not object oriented. 9 | * create global state or variable. 10 | 11 | ![https://media.geeksforgeeks.org/wp-content/uploads/SINGLEton.png](https://media.geeksforgeeks.org/wp-content/uploads/SINGLEton.png) 12 | 13 | 1 . `It should have only one instance` : This is done by providing an instance of the class from within the class. Outer classes or subclasses should be prevented to create the instance. This is done by making the constructor private in java so that no class can access the constructor and hence cannot instantiate it. 14 | 15 | 2 . `Instance should be globally accessible` : Instance of singleton class should be globally accessible so that each class can use it. 16 | 17 | 18 | # Singleton Class Diagram 19 | 20 | * `Static member` : This contains the instance of the singleton class. 21 | * `Private constructor` : This will prevent anybody else to instantiate the Singleton class. 22 | * `Static public method` : This provides the global point of access to the Singleton object and returns the instance to the client calling class. 23 | 24 | 25 | 26 | ```php 27 | your db code 49 | ``` 50 | 51 | # when use singleton pattern 52 | 53 | * hardware interface acccess 54 | * db connection 55 | * logger 56 | * cache 57 | * configure file 58 | 59 | # image 60 | 61 | ![singleton pattern](singleton-pattern.png) 62 | 63 | # resources 64 | 65 | * https://www.codeproject.com/Articles/852232/PHP-Singleton-Pattern-A-Step-by-Step-And-Problem-s 66 | * https://www.youtube.com/watch?v=qWaFiOGwU-8 67 | * https://www.geeksforgeeks.org/singleton-design-pattern-introduction/#:~:text=It%20is%20used%20where%20only,and%20thread%20pool%2C%20database%20connections. 68 | * [laravel framework container](https://github.com/laravel/framework/blob/8.x/src/Illuminate/Container/Container.php#L1315) 69 | * https://dzone.com/articles/singleton-anti-pattern 70 | * https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php 71 | -------------------------------------------------------------------------------- /creational/singleton/singleton-pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code4mk/software-design-pattern/755de56edb0da17a0e3560ff31d9b12494d2d2e0/creational/singleton/singleton-pattern.png -------------------------------------------------------------------------------- /structural/adapter/readme.md: -------------------------------------------------------------------------------- 1 | # Adapter design pattern 2 | 3 | * convert one to another. 4 | 5 | ```php 6 | class SampleBook 7 | { 8 | private $author; 9 | private $title; 10 | public function __construct($author,$title) 11 | { 12 | $this->author = $author; 13 | $this->title = $title; 14 | } 15 | 16 | public function getAuthor() 17 | { 18 | return $this->author; 19 | } 20 | 21 | public function getTitle() 22 | { 23 | return $this->title; 24 | } 25 | } 26 | 27 | class BookAdapter 28 | { 29 | private $book; 30 | 31 | public function __construct(SampleBook $book) 32 | { 33 | $this->book = $book; 34 | } 35 | 36 | public function getAuthorTitle() 37 | { 38 | return $this->book->getAuthor() . ' -- '. $this->book->getTitle(); 39 | } 40 | } 41 | 42 | $book = new SampleBook('kamal',' easy design pattern'); 43 | $bookAdapter = new BookAdapter($book); 44 | 45 | print_r($bookAdapter->getAuthorTitle()); 46 | ``` 47 | 48 | # resource 49 | 50 | * https://www.geeksforgeeks.org/adapter-pattern/ 51 | -------------------------------------------------------------------------------- /structural/decorator/readme.md: -------------------------------------------------------------------------------- 1 | # Decorator design pattern 2 | 3 | * We use the decorator design pattern to add new optional features to our code without changing the existing classes 4 | 5 | 6 | ```php 7 | interface FoodItem 8 | { 9 | public function cost(); 10 | } 11 | // all we need is a burger 12 | class Burger implements FoodItem 13 | { 14 | public function cost () { 15 | return 4; 16 | } 17 | } 18 | // Now decorate with cheese 19 | class Cheese implements FoodItem 20 | { 21 | private $item; 22 | public function __construct (FoodItem $item) { 23 | $this->item = $item; 24 | } 25 | public function cost () { 26 | return $this->item->cost() + 0.25; 27 | } 28 | } 29 | // now decorate with patty 30 | class Patty implements FoodItem 31 | { 32 | private $item; 33 | public function __construct (FoodItem $item) { 34 | $this->item = $item; 35 | } 36 | public function cost () { 37 | return $this->item->cost() + 1; 38 | } 39 | } 40 | $b = new Burger(); 41 | $c = new Cheese($b); // passing burger 42 | $pb = new Patty($b); // passing burger 43 | $pc = new Patty($c); // passing cheese burger 44 | $b->cost(); // 4 45 | $c->cost(); // 4.25 46 | $pb->cost(); // 5 47 | $pc->cost(); // 5.25 48 | ``` 49 | 50 | # resources 51 | 52 | * https://sourcemaking.com/design_patterns/decorator/php 53 | * https://medium.com/@sirajul.anik/understanding-decorator-pattern-with-php-implementation-7f536e742bb0 54 | * https://phpenthusiast.com/blog/the-decorator-design-pattern-in-php-explained 55 | -------------------------------------------------------------------------------- /structural/facades/readme.md: -------------------------------------------------------------------------------- 1 | # Facade design pattern 2 | 3 | * facades hide the implementation 4 | 5 | 6 | ```php 7 | class shareFacade { 8 | // Holds a reference to all of the classes. 9 | protected $twitter; 10 | protected $google; 11 | protected $reddit; 12 | 13 | // The objects are injected to the constructor. 14 | function __construct($twitterObj,$gooleObj,$redditObj) 15 | { 16 | $this->twitter = $twitterObj; 17 | $this->google = $gooleObj; 18 | $this->reddit = $redditObj; 19 | } 20 | 21 | // One function makes all the job of calling all the share methods 22 | // that belong to all the social networks. 23 | function share($url,$title,$status) 24 | { 25 | $this->twitter->tweet($status, $url); 26 | $this->google->share($url); 27 | $this->reddit->reddit($url, $title); 28 | } 29 | } 30 | 31 | // Create the objects from the classes. 32 | $twitterObj = new CodetTwit(); 33 | $gooleObj = new Googlize(); 34 | $redditObj = new Reddiator(); 35 | 36 | // Pass the objects to the class facade object. 37 | $shareObj = new shareFacade($twitterObj,$gooleObj,$redditObj); 38 | 39 | // Call only 1 method to share your post with all the social networks. 40 | $shareObj->share('https://myBlog.com/post-awsome','My greatest post','Read my greatest post ever.'); 41 | ``` 42 | # resources 43 | 44 | * https://designpatternsphp.readthedocs.io/en/latest/Structural/Facade/README.html 45 | * https://dev.to/ahmedash95/design-patterns-in-php-facade-with-laravel-j24 *** 46 | * https://phpenthusiast.com/blog/simplify-your-php-code-with-facade-class 47 | -------------------------------------------------------------------------------- /structural/proxy/readme.md: -------------------------------------------------------------------------------- 1 | # proxy design pattern 2 | 3 | * caching data 4 | 5 | 6 | # resources 7 | 8 | * https://medium.com/@devlob/proxy-design-pattern-to-speed-up-your-applications-2416816493d 9 | -------------------------------------------------------------------------------- /structural/readme.md: -------------------------------------------------------------------------------- 1 | # Structural 2 | 3 | Structural paterns are related to how objects are connected each other. 4 | 5 | # 7 patterns 6 | 7 | 1. decorator 8 | 2. adapter 9 | 3. facades 10 | 4. proxy 11 | 5. bridge 12 | 6. composite 13 | 7. flyweight 14 | -------------------------------------------------------------------------------- /the-solid-principle/readme.md: -------------------------------------------------------------------------------- 1 | SOLID is an acronym that represents a set of principles for writing maintainable and scalable software. These principles were first introduced by Robert C. Martin (also known as Uncle Bob) in his 2000 paper, "Design Principles and Design Patterns." Here is a brief explanation of each of the SOLID principles: 2 | 3 | 1. [Single Responsibility Principle (SRP)](https://github.com/code4mk/software-design-pattern/tree/main/the-solid-principle#single-resposilibity) 4 | 2. [Open-Closed Principle (OCP)](https://github.com/code4mk/software-design-pattern/tree/main/the-solid-principle#openclosed-principle) 5 | 3. [Liskov Substitution Principle (LSP)](https://github.com/code4mk/software-design-pattern/tree/main/the-solid-principle#liskov-substitution) 6 | 4. [Interface Segregation Principle (ISP)](https://github.com/code4mk/software-design-pattern/tree/main/the-solid-principle#interface-segragation) 7 | 5. [Dependency Inversion Principle (DIP)](https://github.com/code4mk/software-design-pattern/tree/main/the-solid-principle#dependency-inversion) 8 | 9 | By following these principles, developers can write software that is easier to maintain, extend, and test. The SOLID principles are widely used in object-oriented programming, and they form the foundation for many design patterns and best practices. 10 | 11 | # Single resposilibity 12 | 13 | Single Responsibility Principle (SRP) is a design principle in object-oriented programming that states that a class should have only one reason to change, i.e., it should have only one responsibility or job. 14 | 15 | In practical terms, this means that a class should be responsible for one thing and one thing only, and that it should not have multiple responsibilities or concerns. This helps to keep classes focused, maintainable, and flexible, and to avoid complex dependencies and coupling between different parts of the code. 16 | 17 | Here is a PHP example of a class that violates the Single Responsibility Principle: 18 | 19 | ```php 20 | class User { 21 | public function register() { 22 | // Register the user 23 | } 24 | 25 | public function login() { 26 | // Log in the user 27 | } 28 | 29 | public function sendEmail() { 30 | // Send an email to the user 31 | } 32 | 33 | public function getProfile() { 34 | // Get the user's profile 35 | } 36 | } 37 | ``` 38 | 39 | In this example, the User class has multiple responsibilities: registering users, logging them in, sending them emails, and retrieving their profiles. This violates the SRP, as each of these responsibilities should be handled by a separate class. 40 | 41 | A better approach would be to split the responsibilities into separate classes, like this: 42 | 43 | ```php 44 | class UserRegistration { 45 | public function register() { 46 | // Register the user 47 | } 48 | } 49 | 50 | class UserLogin { 51 | public function login() { 52 | // Log in the user 53 | } 54 | } 55 | 56 | class UserEmail { 57 | public function sendEmail() { 58 | // Send an email to the user 59 | } 60 | } 61 | 62 | class UserProfile { 63 | public function getProfile() { 64 | // Get the user's profile 65 | } 66 | } 67 | ``` 68 | 69 | # Open/Closed principle 70 | 71 | the Open/Closed Principle (OCP) is a design principle in object-oriented programming that states that a class or module should be open for extension but closed for modification. In other words, you should be able to extend the behavior of a class without modifying its source code. 72 | 73 | Here is a PHP example of a class that violates the Open/Closed Principle: 74 | 75 | ```php 76 | class PaymentProcessor { 77 | public function pay($amount, $paymentMethod) { 78 | if ($paymentMethod == 'credit_card') { 79 | // Process credit card payment 80 | } else if ($paymentMethod == 'paypal') { 81 | // Process PayPal payment 82 | } else if ($paymentMethod == 'bitcoin') { 83 | // Process Bitcoin payment 84 | } else { 85 | throw new Exception('Invalid payment method'); 86 | } 87 | } 88 | } 89 | ``` 90 | 91 | In this example, the PaymentProcessor class has a pay method that accepts an amount and a payment method as parameters. The method then checks the payment method and processes the payment accordingly. However, if a new payment method is added, the class would need to be modified to handle it, which violates the OCP. 92 | 93 | A better approach would be to create a separate class for each payment method, and to make them implement a common interface, like this: 94 | 95 | ```php 96 | interface PaymentMethod { 97 | public function processPayment($amount); 98 | } 99 | 100 | class CreditCardPayment implements PaymentMethod { 101 | public function processPayment($amount) { 102 | // Process credit card payment 103 | } 104 | } 105 | 106 | class PayPalPayment implements PaymentMethod { 107 | public function processPayment($amount) { 108 | // Process PayPal payment 109 | } 110 | } 111 | 112 | class BitcoinPayment implements PaymentMethod { 113 | public function processPayment($amount) { 114 | // Process Bitcoin payment 115 | } 116 | } 117 | 118 | class PaymentProcessor { 119 | public function pay($amount, PaymentMethod $paymentMethod) { 120 | $paymentMethod->processPayment($amount); 121 | } 122 | } 123 | ``` 124 | 125 | This way, the `PaymentProcessor` class is open for extension, as new payment methods can be added by creating new classes that implement the `PaymentMethod` interface, without modifying the `PaymentProcessor` class. This promotes better code organization, reduces coupling, and makes the code more flexible and maintainable. 126 | 127 | 128 | # Liskov substitution 129 | 130 | The Liskov Substitution Principle (LSP) is one of the SOLID principles that states that objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program. In other words, a subclass should be able to be used in place of its parent class without any unexpected behavior. 131 | 132 | example: php 133 | 134 | ```php 135 | width = $width; 147 | } 148 | 149 | public function setHeight($height) { 150 | $this->height = $height; 151 | } 152 | 153 | public function area() { 154 | return $this->width * $this->height; 155 | } 156 | } 157 | 158 | class Square implements Shape { 159 | protected $side; 160 | 161 | public function setSide($side) { 162 | $this->side = $side; 163 | } 164 | 165 | public function area() { 166 | return $this->side * $this->side; 167 | } 168 | } 169 | 170 | function printArea(Shape $shape) { 171 | echo "The area is: " . $shape->area() . "\n"; 172 | } 173 | 174 | $rectangle = new Rectangle(); 175 | $rectangle->setWidth(5); 176 | $rectangle->setHeight(10); 177 | printArea($rectangle); // Output: The area is: 50 178 | 179 | $square = new Square(); 180 | $square->setSide(5); 181 | printArea($square); // Output: The area is: 25 182 | 183 | ``` 184 | 185 | In this example, the `Rectangle` and `Square` classes implement the Shape interface, which has a `area()` method. The `printArea()` function takes a Shape object as a parameter and calls its `area()` method to calculate and print the area. Both `Rectangle` and `Square` classes can be used interchangeably with the `Shape` interface, demonstrating the Liskov Substitution Principle. 186 | 187 | # Interface Segragation 188 | 189 | Interface Segregation Principle (ISP) is a design principle in object-oriented programming that states that a class should not be forced to implement interfaces it does not use. In other words, it is better to have several small and focused interfaces rather than a single large and generic interface. 190 | 191 | ```php 192 | interface Machine { 193 | public function print(); 194 | public function scan(); 195 | public function fax(); 196 | } 197 | 198 | class AllInOnePrinter implements Machine { 199 | public function print() { 200 | // Print the document 201 | } 202 | 203 | public function scan() { 204 | // Scan the document 205 | } 206 | 207 | public function fax() { 208 | // Fax the document 209 | } 210 | } 211 | ``` 212 | 213 | split the interface 214 | 215 | ```php 216 | interface Printer { 217 | public function print(); 218 | } 219 | 220 | interface Scanner { 221 | public function scan(); 222 | } 223 | 224 | interface Fax { 225 | public function fax(); 226 | } 227 | 228 | class AllInOnePrinter implements Printer, Scanner { 229 | public function print() { 230 | // Print the document 231 | } 232 | 233 | public function scan() { 234 | // Scan the document 235 | } 236 | } 237 | 238 | ``` 239 | 240 | # Dependency Inversion 241 | 242 | The Dependency Inversion Principle (DIP) is a design principle in object-oriented programming that states that high-level modules should not depend on low-level modules, but both should depend on abstractions. In other words, a module should depend on an abstract interface, rather than on a concrete implementation. 243 | 244 | Here is a PHP example of a class that violates the Dependency Inversion Principle: 245 | 246 | ```php 247 | class MySQLConnection 248 | { 249 | public function connect() 250 | { 251 | // handle the database connection 252 | return 'Database connection'; 253 | } 254 | } 255 | 256 | class User 257 | { 258 | private $dbConnection; 259 | 260 | public function __construct(MySQLConnection $dbConnection) 261 | { 262 | $this->dbConnection = $dbConnection; 263 | } 264 | } 265 | ``` 266 | 267 | ```php 268 | interface DBConnectionInterface 269 | { 270 | public function connect(); 271 | } 272 | 273 | class MySQLConnection implements DBConnectionInterface 274 | { 275 | public function connect() 276 | { 277 | // handle the database connection 278 | return 'Database connection'; 279 | } 280 | } 281 | 282 | class User 283 | { 284 | private $dbConnection; 285 | 286 | public function __construct(DBConnectionInterface $dbConnection) 287 | { 288 | $this->dbConnection = $dbConnection; 289 | } 290 | } 291 | 292 | ``` 293 | # code smell // 294 | 295 | ~ bad smell / bad practise 296 | 297 | * https://hackernoon.com/5-easy-wins-to-refactor-even-the-worst-legacy-code-7vuc3069 298 | 299 | 300 | # Resources 301 | 302 | 303 | * [successivetech](https://medium.com/successivetech/s-o-l-i-d-the-first-5-principles-of-object-oriented-design-with-php-b6d2742c90d7) 304 | * [SOLID_cheatsheet](https://www.monterail.com/hubfs/PDF%20content/SOLID_cheatsheet.pdf) 305 | * [thinktocode](https://www.thinktocode.com/2017/10/10/solid-principles-in-php/) 306 | * [laracasts](https://laracasts.com/series/solid-principles-in-php) 307 | * [evrtrabajo](https://dev.to/evrtrabajo/solid-in-php-d8e) 308 | * [youtube](https://www.youtube.com/watch?v=rtmFCcjEgEw) 309 | * [youtube laracon](https://www.youtube.com/watch?v=NeXQEJNWO5w) 310 | * [katerina's slide](https://www.slideshare.net/KaterinaTrajchevska/from-good-to-solid-how-to-become-a-better-developer) 311 | 312 | 313 | * [digitalocean](https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design#dependency-inversion-principle) 314 | * [stackify](https://stackify.com/dependency-inversion-principle/#:~:text=Definition%20of%20the%20Dependency%20Inversion%20Principle&text=To%20achieve%20that%2C%20you%20need,level%20modules%20from%20each%20other.&text=Both%20should%20depend%20on%20abstractions,Details%20should%20depend%20on%20abstractions.) --------------------------------------------------------------------------------