├── 1-factory.php ├── 10-composite.php ├── 11-bridge.php ├── 12-flyweight.php ├── 13-strategy.php ├── 14-observer.php ├── 15-command.php ├── 16-chain.php ├── 17-iterator.php ├── 18-mediator.php ├── 19-interpreter.php ├── 2-abstract-factory.php ├── 20-state.php ├── 21-memento.php ├── 22-visitor.php ├── 23-template.php ├── 3-builder.php ├── 4-singleton.php ├── 5-prototype.php ├── 6-adapter.php ├── 7-decorator.php ├── 8-facade.php ├── 9-proxy.php ├── LICENSE.md ├── README.md └── other ├── dependency-injection.php ├── null.php └── servant.php /1-factory.php: -------------------------------------------------------------------------------- 1 | color = $options->color; 17 | $this->doors = $options->doors; 18 | } 19 | 20 | public function info() 21 | { 22 | return "This is a $this->doors doors $this->color car.\n"; 23 | } 24 | } 25 | 26 | // === CarFactory that create Car object for us === 27 | // We can create Car object directly using Car class 28 | // But, by using this factory, we can skip the detail 29 | class CarFactory 30 | { 31 | private $options; 32 | 33 | public function __construct($color, $doors) 34 | { 35 | $options = new CarOptions(); 36 | $options->color = $color; 37 | $options->doors = $doors; 38 | 39 | $this->options = $options; 40 | } 41 | 42 | public function build() 43 | { 44 | return new Car($this->options); 45 | } 46 | } 47 | 48 | // --- 49 | 50 | $factory = new CarFactory("Red", 2); 51 | $car = $factory->build(); 52 | 53 | echo $car->info(); 54 | // Output: This is a 2 doors Red car. 55 | -------------------------------------------------------------------------------- /10-composite.php: -------------------------------------------------------------------------------- 1 | name = $name; 17 | } 18 | 19 | public function honk() 20 | { 21 | echo "$this->name : Honk, honk...\n"; 22 | } 23 | } 24 | 25 | // === Composit === 26 | // Both Leaf and Composit come from same Component 27 | // So, both act the same way. 28 | class CarList implements Honk 29 | { 30 | public $list = []; 31 | 32 | public function add(Car $car) 33 | { 34 | $this->list[] = $car; 35 | } 36 | 37 | public function honk() 38 | { 39 | foreach($this->list as $car) { 40 | $car->honk(); 41 | } 42 | } 43 | } 44 | 45 | // --- 46 | 47 | $fit = new Car("Fit"); 48 | $vitz = new Car("Vitz"); 49 | 50 | $list = new CarList(); 51 | $list->add($fit); 52 | $list->add($vitz); 53 | 54 | $list->honk(); 55 | // Output: 56 | // Fit : Honk, honk... 57 | // Vitz : Honk, honk... 58 | -------------------------------------------------------------------------------- /11-bridge.php: -------------------------------------------------------------------------------- 1 | engine = $engine; 34 | } 35 | 36 | public function set(Engine $engine) 37 | { 38 | $this->engine = $engine; 39 | } 40 | } 41 | 42 | // --- 43 | 44 | $diesel = new Diesel(); 45 | $petrol = new Petrol(); 46 | 47 | $bridge = new EngineBridge($diesel); 48 | $bridge->engine->run(); 49 | // Output: 50 | // Broom! Broom! 51 | 52 | $bridge->set($petrol); 53 | $bridge->engine->run(); 54 | // Output: 55 | // Wroom! Wroom! 56 | -------------------------------------------------------------------------------- /12-flyweight.php: -------------------------------------------------------------------------------- 1 | name = $name; 10 | } 11 | } 12 | 13 | // === A Flyweight === 14 | // That cache objects and re-use when possible 15 | // And create new object only when necessary 16 | class CarFlyweightFactory 17 | { 18 | private $cars = []; 19 | 20 | public function make($name) 21 | { 22 | if (!isset($this->cars[$name])) { 23 | $this->cars[$name] = new Car($name); 24 | } 25 | 26 | return $this->cars[$name]; 27 | } 28 | } 29 | 30 | // --- 31 | 32 | $factory = new CarFlyweightFactory(); 33 | $fit = $factory->make("Fit"); 34 | 35 | echo $fit->name; 36 | // Output: Fit 37 | -------------------------------------------------------------------------------- /13-strategy.php: -------------------------------------------------------------------------------- 1 | today = $today; 35 | } 36 | 37 | public function pick() 38 | { 39 | if( $this->today == "Monday" ) { 40 | $car = new Vitz(); 41 | } else { 42 | $car = new Fit(); 43 | } 44 | 45 | $car->pick(); 46 | } 47 | } 48 | 49 | // --- 50 | 51 | $carpicker = new CarPickerStrategy("Sunday"); 52 | $carpicker->pick(); 53 | // Output: Picking Fit for today. 54 | 55 | $carpicker->today = "Monday"; 56 | $carpicker->pick(); 57 | // Output: Picking Vitz for today. 58 | -------------------------------------------------------------------------------- /14-observer.php: -------------------------------------------------------------------------------- 1 | phones[] = $phone; 15 | } 16 | 17 | public function getStatus() 18 | { 19 | return $this->status; 20 | } 21 | 22 | public function setStatus($status) 23 | { 24 | $this->status = $status; 25 | $this->notify(); 26 | } 27 | 28 | public function notify() { 29 | foreach($this->phones as $phone) { 30 | $phone->update(); 31 | } 32 | } 33 | } 34 | 35 | // === Observer === 36 | // Which add itself to observer-list of subject, 37 | // by invoking attach() method of the subject. 38 | class Phone 39 | { 40 | private $car; 41 | public $name; 42 | 43 | public function __construct(Car $car, $name) 44 | { 45 | $this->name = $name; 46 | $this->car = $car; 47 | $this->car->attach($this); 48 | } 49 | 50 | public function update() 51 | { 52 | echo $this->name . " - Car is " . $this->car->getStatus() . "\n"; 53 | } 54 | } 55 | 56 | // --- 57 | 58 | $car = new Car(); 59 | $iphone = new Phone( $car, "iPhone" ); 60 | $nexus = new Phone( $car, "Nexus" ); 61 | 62 | $car->setStatus("driving"); 63 | // Output: 64 | // iPhone - Car is driving 65 | // Nexus - Car is driving 66 | -------------------------------------------------------------------------------- /15-command.php: -------------------------------------------------------------------------------- 1 | lamp = $lamp; 29 | } 30 | 31 | public function execute() 32 | { 33 | $this->lamp->open(); 34 | } 35 | } 36 | 37 | // === A command that can be executed on Lamp === 38 | class SwitchDown implements Button 39 | { 40 | public $lamp; 41 | 42 | public function __construct(Lamp $lamp) 43 | { 44 | $this->lamp = $lamp; 45 | } 46 | 47 | public function execute() 48 | { 49 | $this->lamp->close(); 50 | } 51 | } 52 | 53 | // === A Collection === 54 | // That accept and execute commands 55 | class Commands 56 | { 57 | public $commands = []; 58 | 59 | public function add(Button $button) 60 | { 61 | $commands[] = $button; 62 | $button->execute(); 63 | } 64 | } 65 | 66 | // --- 67 | 68 | $lamp = new Lamp(); 69 | $up = new SwitchUp($lamp); 70 | $down = new SwitchDown($lamp); 71 | 72 | $commands = new Commands(); 73 | $commands->add($up); 74 | // Output: Lamp is opened. 75 | 76 | $commands->add($down); 77 | // Output: Lamp is closed. 78 | -------------------------------------------------------------------------------- /16-chain.php: -------------------------------------------------------------------------------- 1 | next = $next; 13 | } 14 | 15 | public function runNext(Car $car) 16 | { 17 | if($this->next) { 18 | $this->next->check($car); 19 | } 20 | } 21 | 22 | abstract public function check(Car $car); 23 | } 24 | 25 | // A class that inhirit CarStatus and call runNext() 26 | // to invoke similar function on next object in line 27 | class OilPressure extends CarStatus 28 | { 29 | public function check(Car $car) 30 | { 31 | if( $car->oil != "OK" ) { 32 | echo "Oil Pressure is not OK.\n"; 33 | } else { 34 | echo "Oil Pressure is OK.\n"; 35 | } 36 | 37 | $this->runNext($car); 38 | } 39 | } 40 | 41 | // A class that inhirit CarStatus and call runNext() 42 | // to invoke similar function on next object in line 43 | class FuelLevel extends CarStatus 44 | { 45 | public function check(Car $car) 46 | { 47 | if( $car->fuel != "OK" ) { 48 | echo "Fuel Level is not OK.\n"; 49 | } else { 50 | echo "Fuel Level is OK.\n"; 51 | } 52 | 53 | $this->runNext($car); 54 | } 55 | } 56 | 57 | // A class that inhirit CarStatus and call runNext() 58 | // to invoke similar function on next object in line 59 | class BreakFluid extends CarStatus 60 | { 61 | public function check(Car $car) 62 | { 63 | if( $car->break != "OK" ) { 64 | echo "Break Fluid is not OK.\n"; 65 | } else { 66 | echo "Break Fluid is OK.\n"; 67 | } 68 | 69 | $this->runNext($car); 70 | } 71 | } 72 | 73 | class Car 74 | { 75 | public $oil = "OK"; 76 | public $fuel; 77 | public $break = "OK"; 78 | } 79 | 80 | // --- 81 | 82 | $oil = new OilPressure(); 83 | $fuel = new FuelLevel(); 84 | $break = new BreakFluid(); 85 | 86 | // Setting next objects in line 87 | $oil->setNext($fuel); 88 | $fuel->setNext($break); 89 | 90 | $oil->check(new Car()); 91 | // Output: 92 | // Oil Pressure is OK. 93 | // Fuel Level is not OK. 94 | // Break Fluid is OK. 95 | -------------------------------------------------------------------------------- /17-iterator.php: -------------------------------------------------------------------------------- 1 | cars = $cars; 14 | } 15 | 16 | public function current() 17 | { 18 | return $this->cars->getName($this->position); 19 | } 20 | 21 | public function key() 22 | { 23 | return $this->position; 24 | } 25 | 26 | public function next() 27 | { 28 | $this->position++; 29 | } 30 | 31 | public function rewind() 32 | { 33 | $this->position = 0; 34 | } 35 | 36 | public function valid() 37 | { 38 | return !is_null($this->cars->getName($this->position)); 39 | } 40 | } 41 | 42 | // === PHP has build-in IteratorAggregate interface === 43 | // That enforce getIterator() method to work 44 | // in conjunction with Iterator interface 45 | class CarCollection implements IteratorAggregate 46 | { 47 | private $names = []; 48 | 49 | public function getIterator() 50 | { 51 | return new CarIterator($this); 52 | } 53 | 54 | public function setName($string) 55 | { 56 | $this->names[] = $string; 57 | } 58 | 59 | public function getName($key) 60 | { 61 | if (isset($this->names[$key])) { 62 | return $this->names[$key]; 63 | } 64 | 65 | return null; 66 | } 67 | 68 | public function is_empty() 69 | { 70 | return empty($this->$names); 71 | } 72 | } 73 | 74 | // --- 75 | 76 | $cars = new CarCollection(); 77 | 78 | $cars->setName('Fit'); 79 | $cars->setName('Vitz'); 80 | $cars->setName('Swift'); 81 | 82 | foreach($cars as $car){ 83 | echo $car . "\n"; 84 | } 85 | 86 | // Output: 87 | // Fit 88 | // Vitz 89 | // Swift 90 | -------------------------------------------------------------------------------- /18-mediator.php: -------------------------------------------------------------------------------- 1 | filters[] = $filter; 36 | } 37 | 38 | public function check() 39 | { 40 | foreach ($this->filters as $filter) { 41 | $filter->check(); 42 | } 43 | } 44 | } 45 | 46 | $car = new Car(); 47 | $car->addFilter( new OilFilter() ); 48 | $car->addFilter( new AirFilter() ); 49 | $car->check(); 50 | 51 | // Output: 52 | // Checking Oil Filter... OK 53 | // Checking Air Filter... OK 54 | -------------------------------------------------------------------------------- /19-interpreter.php: -------------------------------------------------------------------------------- 1 | gallon = $gallon; 17 | } 18 | 19 | public function show() 20 | { 21 | return round($this->gallon * 3.79); 22 | } 23 | } 24 | 25 | // === A Simple Converter === 26 | // That convert Mile to Kilometer 27 | class MileToKilometer implements Converter 28 | { 29 | private $mile; 30 | 31 | public function __construct($mile) 32 | { 33 | $this->mile = $mile; 34 | } 35 | 36 | public function show() 37 | { 38 | return round($this->mile * 1.6); 39 | } 40 | } 41 | 42 | // === An Intepreter === 43 | // That interpret to Kilometer per Litre by using existing converters. 44 | // Consider this as structuring a sentence using grammers (converters). 45 | class MpgToKml implements Converter 46 | { 47 | private $g2l; 48 | private $m2k; 49 | 50 | public function __construct(Converter $g2l, Converter $m2k) 51 | { 52 | $this->g2l = $g2l; 53 | $this->m2k = $m2k; 54 | } 55 | 56 | public function show() 57 | { 58 | echo $this->g2l->show() . "l/" . $this->m2k->show() . "k\n"; 59 | } 60 | } 61 | 62 | // --- 63 | 64 | $mpg2kml = new MpgToKml(new GallonToLitre(1), new MileToKilometer(20)); 65 | $mpg2kml->show(); 66 | // Output: 4l/32k 67 | -------------------------------------------------------------------------------- /2-abstract-factory.php: -------------------------------------------------------------------------------- 1 | color = $options->color; 17 | $this->doors = $options->doors; 18 | } 19 | 20 | public function info() 21 | { 22 | return "This is a $this->doors doors $this->color car.\n"; 23 | } 24 | } 25 | 26 | // === Abstract/Guideline to creat CarFactory === 27 | // This help use create interchangable factories 28 | // See also: Factory Method pattern 29 | abstract class CarFactory 30 | { 31 | abstract public function build(); 32 | } 33 | 34 | class RedCarFactory extends CarFactory 35 | { 36 | private $options; 37 | 38 | public function __construct($doors) 39 | { 40 | $options = new CarOptions(); 41 | $options->color = "Red"; 42 | $options->doors = $doors; 43 | 44 | $this->options = $options; 45 | } 46 | 47 | public function build() 48 | { 49 | return new Car($this->options); 50 | } 51 | } 52 | 53 | class BlueCarFactory extends CarFactory 54 | { 55 | private $options; 56 | 57 | public function __construct($doors) 58 | { 59 | $options = new CarOptions(); 60 | $options->color = "Blue"; 61 | $options->doors = $doors; 62 | 63 | $this->options = $options; 64 | } 65 | 66 | public function build() 67 | { 68 | return new Car($this->options); 69 | } 70 | } 71 | 72 | // --- 73 | 74 | $color = "Blue"; 75 | 76 | // Deciding which factory to use 77 | if($color == "Blue") { 78 | $factory = new BlueCarFactory(5); 79 | } elseif($color == "Red") { 80 | $factory = new RedCarFactory(4); 81 | } 82 | 83 | $car = $factory->build(); 84 | echo $car->info(); 85 | // Output: This is a 5 doors Blue car. 86 | -------------------------------------------------------------------------------- /20-state.php: -------------------------------------------------------------------------------- 1 | state = $state; 53 | } 54 | 55 | public function drive() 56 | { 57 | $this->setState($this->state->drive()); 58 | } 59 | 60 | public function stop() 61 | { 62 | $this->setState($this->state->stop()); 63 | } 64 | 65 | private function setState(StateInterface $state) 66 | { 67 | $this->state = $state; 68 | } 69 | } 70 | 71 | // --- 72 | 73 | // The car is initially stop 74 | $car = new Car(new StopState()); 75 | 76 | // So, it's allow to drive 77 | $car->drive(); 78 | // Output: The car is driving now. 79 | 80 | // Now it's driving, so, 81 | // it's allow to stop once again 82 | $car->stop(); 83 | // Output: The car is stopped. 84 | 85 | // Now it has stopped, so, 86 | // not allow to stop again 87 | $car->stop(); 88 | // Output: You are not allow to stop. 89 | -------------------------------------------------------------------------------- /21-memento.php: -------------------------------------------------------------------------------- 1 | car = $car; 12 | } 13 | 14 | public function getCar() 15 | { 16 | return $this->car; 17 | } 18 | } 19 | 20 | class Car 21 | { 22 | public $color; 23 | 24 | public function __construct($color) 25 | { 26 | $this->color = $color; 27 | } 28 | } 29 | 30 | class Customizer 31 | { 32 | private $car; 33 | 34 | public function __construct(Car $car) 35 | { 36 | $this->car = $car; 37 | } 38 | 39 | // Store backup copy in Memento 40 | public function copy() 41 | { 42 | return new Memento( clone $this->car ); 43 | } 44 | 45 | // Retrive backup from Memento 46 | public function restore(Memento $memento) 47 | { 48 | $this->car = $memento->getCar(); 49 | } 50 | 51 | public function changeColor($color) 52 | { 53 | $this->car->color = $color; 54 | } 55 | 56 | public function getColor() 57 | { 58 | return $this->car->color; 59 | } 60 | } 61 | 62 | // --- 63 | 64 | $custom = new Customizer( new Car("White") ); 65 | echo $custom->getColor() . "\n"; 66 | // Output: White 67 | 68 | $backup = $custom->copy(); 69 | 70 | $custom->changeColor("Black"); 71 | echo $custom->getColor() . "\n"; 72 | // Output: Black 73 | 74 | $custom->restore($backup); 75 | echo $custom->getColor() . "\n"; 76 | // Output: White 77 | -------------------------------------------------------------------------------- /22-visitor.php: -------------------------------------------------------------------------------- 1 | color = $enhancer->enhance( $this ); 11 | } 12 | } 13 | 14 | // === A visitor === 15 | // That can visit into Car object change it 16 | // The benefit is, Car object is now seperated from 17 | // detail algorithm of how it can be enhanced 18 | class Enhancer 19 | { 20 | // visiting into Car 21 | public function enhance(Car $car) 22 | { 23 | return "Matelic $car->color"; 24 | } 25 | } 26 | 27 | // --- 28 | 29 | $car = new Car(); 30 | echo $car->color . "\n"; 31 | // Output: Silver 32 | 33 | $car->visitor(new Enhancer()); 34 | echo $car->color . "\n"; 35 | // Output: Matelic Silver 36 | -------------------------------------------------------------------------------- /23-template.php: -------------------------------------------------------------------------------- 1 | name = $name; 12 | } 13 | 14 | public function loadPassenger() 15 | { 16 | echo "The $this->name is loading passengers...\n"; 17 | } 18 | } 19 | 20 | class Minivan extends Car 21 | { 22 | public $doors = 5; 23 | 24 | public function loadGrocery() 25 | { 26 | echo "The $this->name is loading grocery...\n"; 27 | } 28 | } 29 | 30 | class SportCar extends Car 31 | { 32 | public $doors = 2; 33 | public $color = "Red"; 34 | 35 | public function loadPassenger() 36 | { 37 | echo "The $this->name is loading a buddy...\n"; 38 | } 39 | } 40 | 41 | // --- 42 | 43 | $fit = new Minivan("Fit"); 44 | $fit->loadPassenger(); 45 | // Output: The Fit is loading passengers... 46 | 47 | $evo = new SportCar("Evo"); 48 | $evo->loadPassenger(); 49 | // Output: The Evo is loading a buddy... 50 | -------------------------------------------------------------------------------- /3-builder.php: -------------------------------------------------------------------------------- 1 | color = $color; 14 | return $this; 15 | } 16 | 17 | public function setDoors($doors) 18 | { 19 | $this->doors = $doors; 20 | return $this; 21 | } 22 | 23 | public function getColor() 24 | { 25 | return $this->color; 26 | } 27 | 28 | public function getDoors() 29 | { 30 | return $this->doors; 31 | } 32 | 33 | function build() 34 | { 35 | return new Car($this); 36 | } 37 | } 38 | 39 | class Car 40 | { 41 | public $color; 42 | public $doors; 43 | 44 | public function __construct(CarBuilder $cb) 45 | { 46 | $this->color = $cb->getColor(); 47 | $this->doors = $cb->getDoors(); 48 | } 49 | 50 | static function builder() 51 | { 52 | return new CarBuilder(); 53 | } 54 | } 55 | 56 | // --- 57 | 58 | $car = Car::builder()->setColor("Silver")->setDoors(5)->build(); 59 | 60 | print_r($car); 61 | // Output: Car Object([color] => Silver, [doors] => 5) 62 | -------------------------------------------------------------------------------- /4-singleton.php: -------------------------------------------------------------------------------- 1 | info = "I am a single.\n"; 14 | } 15 | 16 | static function make() 17 | { 18 | if (!static::$me) { 19 | static::$me = new static; 20 | } 21 | 22 | return static::$me; 23 | } 24 | } 25 | 26 | // --- 27 | 28 | $single = Single::make(); 29 | echo $single->info; 30 | // Output: I'm a single. 31 | -------------------------------------------------------------------------------- /5-prototype.php: -------------------------------------------------------------------------------- 1 | White, [doors] => 4) 27 | -------------------------------------------------------------------------------- /6-adapter.php: -------------------------------------------------------------------------------- 1 | socket = $socket; 56 | } 57 | 58 | public function one() 59 | { 60 | $this->socket->one(); 61 | } 62 | 63 | public function two() 64 | { 65 | $this->socket->two(); 66 | } 67 | 68 | public function three() 69 | { 70 | echo "Pin three doesn't exists, but it's OK.\n"; 71 | } 72 | } 73 | 74 | class Lamp 75 | { 76 | private $socket; 77 | 78 | public function __construct(ThreePins $socket) 79 | { 80 | $this->socket = $socket; 81 | } 82 | 83 | public function turnOn() { 84 | $this->socket->one(); 85 | $this->socket->two(); 86 | $this->socket->three(); 87 | } 88 | } 89 | 90 | // --- 91 | 92 | $threepins = new ThreePinsSocket(); 93 | $twopins = new ThreePinsAdapter(new TwoPinsSocket()); 94 | 95 | $lamp1 = new Lamp($threepins); 96 | $lamp1->turnOn(); 97 | // Output: 98 | // Pin one exists. 99 | // Pin two exists. 100 | // Pin three exists. 101 | 102 | $lamp2 = new Lamp($twopins); 103 | $lamp2->turnOn(); 104 | // Output: 105 | // Pin one exists. 106 | // Pin two exists. 107 | // Pin three doesn't exists, but it's OK. 108 | -------------------------------------------------------------------------------- /7-decorator.php: -------------------------------------------------------------------------------- 1 | features = "Alloy Wheel"; 15 | } 16 | } 17 | 18 | abstract class CarDecorator implements CarInterface 19 | { 20 | protected $car; 21 | 22 | public function __construct(CarInterface $car) 23 | { 24 | $this->car = $car; 25 | } 26 | 27 | abstract public function setup(); 28 | } 29 | 30 | // === A CarDecorator that can add === 31 | // additional feature to existing Car object 32 | class SunroofDecorator extends CarDecorator 33 | { 34 | public function setup() 35 | { 36 | $this->car->setup(); 37 | $this->car->features .= ", Sunroof"; 38 | $this->features = $this->car->features; 39 | } 40 | } 41 | 42 | // === A CarDecorator that can add === 43 | // additional feature to existing Car object 44 | class SpoilerDecorator extends CarDecorator 45 | { 46 | public function setup() 47 | { 48 | $this->car->setup(); 49 | $this->car->features .= ", Spoiler"; 50 | $this->features = $this->car->features; 51 | } 52 | } 53 | 54 | // --- 55 | 56 | $car = new Car(); 57 | $car = new SunroofDecorator($car); 58 | $car = new SpoilerDecorator($car); 59 | $car->setup(); 60 | 61 | echo $car->features; 62 | // Output: Alloy Wheel, Sunroof, Spoiler 63 | -------------------------------------------------------------------------------- /8-facade.php: -------------------------------------------------------------------------------- 1 | oil = new CheckOilPressure(); 39 | $this->fuel = new CheckFuel(); 40 | $this->break = new CheckBreakFluid(); 41 | } 42 | 43 | public function start() 44 | { 45 | $this->oil->check(); 46 | $this->fuel->check(); 47 | $this->break->check(); 48 | 49 | echo "Car Engine Started.\n"; 50 | } 51 | } 52 | 53 | // --- 54 | 55 | $car = new Car(); 56 | $car->start(); 57 | 58 | // Output: 59 | // Oil Pressure OK. 60 | // Fuel Status OK. 61 | // Break Fluid OK. 62 | // Car Engine Started. 63 | -------------------------------------------------------------------------------- /9-proxy.php: -------------------------------------------------------------------------------- 1 | car = $car; 21 | } 22 | 23 | public function start() 24 | { 25 | new Car( $this->car ); 26 | } 27 | } 28 | 29 | // --- 30 | 31 | $cars = [ new CarProxy("Fit"), new CarProxy("Vitz") ]; 32 | $cars[1]->start(); 33 | // Output: The Vitz has started and ready. 34 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2018 Ei Maung 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 by Examples in PHP 2 | 3 | Most simplest design pattern implementation in PHP, including all 23 GoF patterns plus some other patterns. These code are part of **PHP Framework Course** provided by [Fairway Technology](https://fairway.com.mm). 4 | 5 | ## How to learn? 6 | 7 | Read the code. 8 | 9 | ### Creational Patterns 10 | 1. [Factory Method](1-factory.php) 11 | 2. [Abstract Factory](2-abstract-factory.php) 12 | 3. [Builder](3-builder.php) 13 | 4. [Singleton](4-singleton.php) 14 | 5. [Prototype](5-prototype.php) 15 | 16 | ### Structural Patterns 17 | 1. [Adapter](6-adapter.php) 18 | 2. [Decorator](7-decorator.php) 19 | 3. [Facade](8-facade.php) 20 | 4. [Proxy](9-proxy.php) 21 | 5. [Composite](10-composite.php) 22 | 6. [Bridge](11-bridge.php) 23 | 7. [Flyweight](12-flyweight.php) 24 | 25 | ### Behavioral Patterns 26 | 1. [Strategy](13-strategy.php) 27 | 2. [Observer](14-observer.php) 28 | 3. [Command](15-command.php) 29 | 4. [Chain of Responsibility](16-chain.php) 30 | 5. [Iterator](17-iterator.php) 31 | 6. [Mediator](18-mediator.php) 32 | 7. [Interpreter](19-interpreter.php) 33 | 8. [State](20-state.php) 34 | 9. [Memento](21-memento.php) 35 | 10. [Visitor](22-visitor.php) 36 | 11. [Template](23-template.php) 37 | 38 | ### Other (non-GoF) 39 | 1. [Dependency Injection](other/dependency-injection.php) 40 | 2. [Null Object](other/null.php) 41 | 3. [Servant](other/servant.php) 42 | 43 | ## Note 44 | 45 | These code are oversimplified by design and may not follow all best practices. Use this only as education purpose in attempt to understand the patterns, not as direct example to use in real projects. 46 | 47 | ## License and Contact 48 | 49 | * License - [MIT License](LICENSE.md) 50 | * Website - [eimaung.com](https://eimaung.com) 51 | * Email - [eimg@fairwayweb.com](mailto:eimg@fairwayweb.com) 52 | -------------------------------------------------------------------------------- /other/dependency-injection.php: -------------------------------------------------------------------------------- 1 | options = $options; 21 | } 22 | 23 | public function getColor() 24 | { 25 | return $this->options->color; 26 | } 27 | } 28 | 29 | $car = new Car( new CarOptions() ); 30 | echo $car->getColor() . "\n"; 31 | // Output: White 32 | 33 | // === Interface & Setter Injection === 34 | interface CarInterface 35 | { 36 | public function setOptions(CarOptions $options); 37 | } 38 | 39 | class Car2 implements CarInterface 40 | { 41 | private $options; 42 | 43 | public function setOptions(CarOptions $options) 44 | { 45 | $this->options = $options; 46 | } 47 | 48 | public function getColor() 49 | { 50 | return $this->options->color ?? null; 51 | } 52 | } 53 | 54 | $car2 = new Car2(); 55 | $car2->setOptions( new CarOptions() ); 56 | echo $car2->getColor() . "\n"; 57 | // Output: White 58 | -------------------------------------------------------------------------------- /other/null.php: -------------------------------------------------------------------------------- 1 | drive(); 47 | // Output: [nothing] 48 | 49 | // We avoided `Call to a memeber function on null` error here. 50 | // Without NullCar object the code will look like following 51 | // to avoid such error. 52 | // 53 | // if( isset($car) and $car instanceof Car ) { 54 | // $car->drive(); 55 | // } 56 | -------------------------------------------------------------------------------- /other/servant.php: -------------------------------------------------------------------------------- 1 | width > $car->getWidth()) { 11 | echo "Parking OK\n"; 12 | } else { 13 | echo "Parking not OK\n"; 14 | } 15 | } 16 | } 17 | 18 | // Every Class that want to use Parking servent 19 | // must implement this interface 20 | interface Car 21 | { 22 | public function check(Parking $parking); 23 | public function getWidth(); 24 | } 25 | 26 | class Van implements Car 27 | { 28 | private $width = 1.8; 29 | 30 | public function check(Parking $parking) 31 | { 32 | $parking->check($this); 33 | } 34 | 35 | public function getWidth() { 36 | return $this->width; 37 | } 38 | } 39 | 40 | class Bus implements Car 41 | { 42 | private $width = 2.2; 43 | 44 | public function check(Parking $parking) 45 | { 46 | $parking->check($this); 47 | } 48 | 49 | public function getWidth() { 50 | return $this->width; 51 | } 52 | } 53 | 54 | // --- 55 | 56 | (new Van())->check(new Parking()); 57 | // Output: Parking OK 58 | 59 | (new Bus())->check(new Parking()); 60 | // Output: Parking not OK 61 | --------------------------------------------------------------------------------