1 of 54

Design Patterns in 30 Minutes.

2 of 54

HELLO!

I am Win Yu.

2

3 of 54

Outline

3

Design Patterns

Creational

Structal

Behavioral

4 of 54

Design Patterns

4

5 of 54

5

💁‍♂️ Design patterns are solutions to recurring problems; guidelines on how to tackle certain problems.

💣 Design patterns are not a silver bullet to all your problems.

6 of 54

KISS

Keep It Simple Stupid.

DRY

Don’t Repeat Yourself.

Maintainable

  • Understandable
  • Extendable
  • Debuggable

Design Patterns

7 of 54

Common Types

7

Creational

Behavioral

Structural

8 of 54

1.

Creational

8

9 of 54

Creational patterns are focused towards how to instantiate an object or group of related objects.

9

— Class instantiation

— Hiding the creation logic

10 of 54

  • Factory Method
  • Abstract Factory
  • Builder
  • Prototype
  • Singleton

10

11 of 54

  • Factory Method
  • Abstract Factory
  • Builder( (Manager)
  • Prototype
  • Singleton

11

12 of 54

Builder(Manager) Pattern

Allows you to create different flavors of an object while avoiding constructor pollution.

12

Wikipedia says

The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor anti-pattern.

13 of 54

13

Builder 模式一步一步建立實體物件的部分組成,最後再回傳一個完整的物件

14 of 54

Telescoping constructor anti-pattern

public function __construct($size, $cheese = true, $pepperoni = true, $tomato = false, $lettuce = true){�}

14

15 of 54

We have a burger.

class Burger�{� protected $size;�� protected $cheese = false;� protected $pepperoni = false;� protected $lettuce = false;� protected $tomato = false;�� public function __construct(BurgerBuilder $builder)� {� $this->size = $builder->size;� $this->cheese = $builder->cheese;� $this->pepperoni = $builder->pepperoni;� $this->lettuce = $builder->lettuce;� $this->tomato = $builder->tomato;� }�}

15

16 of 54

We have the builder.

class BurgerBuilder�{� public $size;�� public $cheese = false;� public $pepperoni = false;� public $lettuce = false;� public $tomato = false;�� public function __construct(int $size)� {� $this->size = $size;� }�� public function addPepperoni()� {� $this->pepperoni = true;� return $this;� }� public function addLettuce()� {� $this->lettuce = true;� return $this;� }...

public function addCheese()� {� $this->cheese = true;� return $this;� }�� public function addTomato()� {� $this->tomato = true;� return $this;� }�� public function build(): Burger� {� return new Burger($this);� }�}

16

17 of 54

Create burger via builder.

$burger = (new BurgerBuilder(14))� ->addPepperoni()� ->addLettuce()� ->addTomato()� ->build();

17

18 of 54

Laravel Manager Pattern Examples

Illuminate\Auth\AuthManager

Illuminate\Broadcasting\BroadcastManager

Illuminate\Cache\CacheManager

Illuminate\Filesystem\FilesystemManager

Illuminate\Mail\TransportManager

Illuminate\Notifications\ChannelManager

Illuminate\Queue\QueueManager

Illuminate\Session\SessionManager

18

19 of 54

Singleton Pattern

Ensures that only one object of a particular class is ever created.

19

20 of 54

20

確保類別只有一個實例(instance),

並提供所有使用對象該實例的方法

21 of 54

To create a singleton, make the constructor private, disable cloning, disable extension and create a static variable to house the instance

final class President�{� private static $instance;�� private function __construct()� {� // Hide the constructor� }�� public static function getInstance(): President� {� if (!self::$instance) {� self::$instance = new self();� }�� return self::$instance;� }�� private function __clone()� {� // Disable cloning� }�� private function __wakeup()� {� // Disable unserialize� }�}

21

22 of 54

Verify

$president1 = President::getInstance();�$president2 = President::getInstance();��var_dump($president1 === $president2); // true

22

23 of 54

Singleton in Service Container

23

https://blog.albert-chen.com

24 of 54

2.

Structural

24

25 of 54

Structural patterns are mostly concerned with object composition or in other words how the entities can use each other.

> "How to build a software component?"

25

Composition between objects

— Usages of interfaces, abstract classes

26 of 54

  • Adapter
  • Bridge
  • Composite
  • Decorator
  • Facade
  • Flyweight
  • Proxy

26

27 of 54

  • Adapter
  • Bridge
  • Composite
  • Decorator
  • Facade
  • Flyweight
  • Proxy

27

28 of 54

Composite Pattern

Composite pattern lets clients treat the individual objects in a uniform manner.

28

29 of 54

29

組合模式可以表示單一物件群體階層的關係。

群體為這單一物件的相同型別集合,

他們有著相同的行為

30 of 54

Different employee types

interface Employee�{� public function __construct(string $name, float $salary);� public function getName(): string;� public function setSalary(float $salary);� public function getSalary(): float;�}

class Developer implements Employee�{� protected $salary;� protected $name;� � public function __construct(string $name, float $salary)� {� $this->name = $name;� $this->salary = $salary;� }�� public function getName(): string� {� return $this->name;� }�� public function setSalary(float $salary)� {� $this->salary = $salary;� }�� public function getSalary(): float� {� return $this->salary;� }�}�

class Designer implements Employee�{� protected $salary;� protected $name;� � public function __construct(string $name, float $salary)� {� $this->name = $name;� $this->salary = $salary;� }�� public function getName(): string� {� return $this->name;� }�� public function setSalary(float $salary)� {� $this->salary = $salary;� }�� public function getSalary(): float� {� return $this->salary;� }�}�

30

31 of 54

The organization which consists of several different types of employees

// Prepare the employees�$john = new Developer('John Doe', 12000);�$jane = new Designer('Jane Doe', 15000);��// Add them to organization�$organization = new Organization();�$organization->addEmployee($john);�$organization->addEmployee($jane);��echo "Net salaries: " . $organization->getNetSalaries();

// Net Salaries: 27000

class Organization�{� protected $employees;�� public function addEmployee(Employee $employee)� {� $this->employees[] = $employee;� }�� public function getNetSalaries(): float� {� $netSalary = 0;�� foreach ($this->employees as $employee) {� $netSalary += $employee->getSalary();� }�� return $netSalary;� }�}

31

32 of 54

Facade Pattern

Facade pattern provides a simplified interface to a complex subsystem.

32

33 of 54

33

封裝商業邏輯並提供簡單介面,以達到

易使用、可讀性提高、減少依賴的目的

34 of 54

We have the computer class.

class Computer�{� public function getElectricShock()� {� echo "Ouch!";� }�� public function makeSound()� {� echo "Beep beep!";� }�� public function showLoadingScreen()� {� echo "Loading..";� }�� public function bam()� {� echo "Ready to be used!";� }��

public function closeEverything()� {� echo "Bup bup bup buzzzz!";� }�� public function sooth()� {� echo "Zzzzz";� }�� public function pullCurrent()� {� echo "Haaah!";� }�}

34

35 of 54

We have the Facade

class ComputerFacade�{� protected $computer;�� public function __construct(Computer $computer)� {� $this->computer = $computer;� }�� public function turnOn()� {� $this->computer->getElectricShock();� $this->computer->makeSound();� $this->computer->showLoadingScreen();� $this->computer->bam();� }�� public function turnOff()� {� $this->computer->closeEverything();� $this->computer->pullCurrent();� $this->computer->sooth();� }�}

35

36 of 54

Now to use the facade

$computer = new ComputerFacade(new Computer());�$computer->turnOn(); // Ouch! Beep beep! Loading.. Ready to be used!�$computer->turnOff(); // Bup bup buzzz! Haah! Zzzzz

36

37 of 54

Laravel Facade Pattern Examples

Illuminate\Support\Facades\Facade.php

Illuminate\Support\Facades\App.php

Illuminate\Support\Facades\Blade.php

Illuminate\Support\Facades\Cache.php

Illuminate\Support\Facades\DB.php

Illuminate\Support\Facades\File.php

Illuminate\Support\Facades\Queue.php

Illuminate\Support\Facades\Response.php

…...

37

38 of 54

Facades in Laravel

38

39 of 54

3.

Behavioral

39

40 of 54

It is concerned with assignment of responsibilities between the objects.

40

— Communication between objects

— Usages of mostly interfaces

41 of 54

Structural pattern vs. Behavioral pattern

The Behavioral patterns don't just specify the structure but also outline the patterns for message passing/communication between them.

In other words, they assist in answering :

"How to run a behavior in software component?"

41

42 of 54

  • Chain of Responsibility
  • Command
  • Iterator
  • Mediator
  • Memento
  • Observer
  • Visitor
  • Strategy
  • State
  • Template Method

42

43 of 54

  • Chain of Responsibility
  • Command
  • Iterator
  • Mediator
  • Memento
  • Observer
  • Visitor
  • Strategy
  • State
  • Template Method

43

44 of 54

Strategy Pattern

Strategy pattern allows you to switch the algorithm or strategy based upon the situation.

44

45 of 54

45

定義多個演算法,各別封裝這些演算法,

並讓它們可以互換

46 of 54

interface SortStrategy�{� public function sort(array $dataset): array;�}��class BubbleSortStrategy implements SortStrategy�{� public function sort(array $dataset): array� {� echo "Sorting using bubble sort";�� // Do sortingreturn $dataset;� }�}��class QuickSortStrategy implements SortStrategy�{� public function sort(array $dataset): array� {� echo "Sorting using quick sort";�� // Do sortingreturn $dataset;� }�}

class Sorter�{� protected $sorter;�� public function __construct(SortStrategy $sorter)� {� $this->sorter = $sorter;� }�� public function sort(array $dataset): array� {� return $this->sorter->sort($dataset);� }�}

46

47 of 54

Decide your strategy via Sorter

$dataset = [1, 5, 4, 3, 2, 8];��$sorter = new Sorter(new BubbleSortStrategy());�$sorter->sort($dataset); // Output : Sorting using bubble sort��$sorter = new Sorter(new QuickSortStrategy());�$sorter->sort($dataset); // Output : Sorting using quick sort

47

48 of 54

Template Pattern

Template method defines the skeleton of how a certain algorithm could be performed, but defers the implementation of those steps to the children classes.

48

49 of 54

49

定義一個包含方法和執行流程的抽象樣板,

讓實作類別透過繼承的方式實作方法的細節。

最後透過樣板已經定義好的流程執行

50 of 54

Define abstract class

abstract class Builder�{�� // Template methodfinal public function build()� {� $this->test();� $this->lint();� $this->assemble();� $this->deploy();� }�� abstract public function test();� abstract public function lint();� abstract public function assemble();� abstract public function deploy();�}

50

51 of 54

class AndroidBuilder extends Builder�{� public function test()� {� echo 'Running android tests';� }�� public function lint()� {� echo 'Linting the android code';� }�� public function assemble()� {� echo 'Assembling the android build';� }�� public function deploy()� {� echo 'Deploying android build to server';� }�}

class IosBuilder extends Builder�{� public function test()� {� echo 'Running ios tests';� }�� public function lint()� {� echo 'Linting the ios code';� }�� public function assemble()� {� echo 'Assembling the ios build';� }�� public function deploy()� {� echo 'Deploying ios build to server';� }�}

51

52 of 54

Use your strategy for different scenarios.

$androidBuilder = new AndroidBuilder();�$androidBuilder->build();��// Output:// Running android tests// Linting the android code// Assembling the android build// Deploying android build to server��$iosBuilder = new IosBuilder();�$iosBuilder->build();��// Output:// Running ios tests// Linting the ios code// Assembling the ios build// Deploying ios build to server

52

53 of 54

See more in my references

53

54 of 54

THANKS!

Any questions?

54