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

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

7 |

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

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