├── .gitignore ├── Behavioral ├── ChainOfResponsobility │ ├── Logger.php │ ├── Logger │ │ ├── Email.php │ │ ├── File.php │ │ └── Profiling.php │ ├── LoggerHelper.php │ ├── README.md │ └── Test.php ├── Command │ ├── Calculator.php │ ├── Operation.php │ ├── Operation │ │ ├── Division.php │ │ ├── Minus.php │ │ ├── Multiplication.php │ │ └── Plus.php │ ├── OperationHelper.php │ ├── README.md │ ├── Test.php │ └── Window.php ├── Interpreter │ ├── Context.php │ ├── Expression.php │ ├── Expression │ │ ├── Minus.php │ │ ├── Plus.php │ │ └── Variable.php │ ├── README.md │ └── Test.php ├── Iterator │ ├── Aggregator.php │ ├── Aggregator │ │ └── Shop.php │ ├── Iterator.php │ ├── Iterator │ │ └── Shop.php │ ├── README.md │ └── Test.php ├── Mediator │ ├── Colleaque.php │ ├── Colleque │ │ ├── AuthorBook.php │ │ └── TitleBook.php │ ├── Mediator.php │ ├── Mediator │ │ └── Book.php │ ├── README.md │ └── Test.php ├── Memento │ ├── Caretaker.php │ ├── Memento.php │ ├── Originator.php │ ├── README.md │ └── Test.php ├── Observer │ ├── Observable.php │ ├── Observable │ │ └── WeatherStation.php │ ├── Observer.php │ ├── Observer │ │ ├── WeatherCustomer.php │ │ └── WeatherCustomerDelegate.php │ ├── README.md │ ├── README.ru.md │ └── Test.php ├── README.md ├── State │ ├── Context.php │ ├── README.md │ ├── State.php │ ├── State │ │ ├── A.php │ │ ├── B.php │ │ └── C.php │ └── Test.php ├── Strategy │ ├── BillingStrategy.php │ ├── BillingStrategy │ │ ├── HappyHour.php │ │ └── Normal.php │ ├── Customer.php │ ├── README.md │ └── Test.php ├── TemplateMethod │ ├── Game.php │ ├── Game │ │ ├── Basketball.php │ │ └── Football.php │ ├── README.md │ ├── README.ru.md │ └── Test.php └── Visitor │ ├── Item.php │ ├── Item │ ├── Book.php │ └── Fruit.php │ ├── ItemVisitor.php │ ├── ItemVisitor │ └── Price.php │ ├── README.md │ └── Test.php ├── Creational ├── AbstractFactory │ ├── Book.php │ ├── Book │ │ ├── MySQL.php │ │ ├── MySQL │ │ │ ├── Piter.php │ │ │ └── Williams.php │ │ ├── PHP.php │ │ └── PHP │ │ │ ├── Piter.php │ │ │ └── Williams.php │ ├── BookFactory.php │ ├── BookFactory │ │ ├── Piter.php │ │ └── Williams.php │ ├── BookHelper.php │ ├── README.md │ └── Test.php ├── Builder │ ├── Builder.php │ ├── Builder │ │ ├── Car.php │ │ └── Plane.php │ ├── Manager.php │ ├── Product.php │ ├── README.md │ └── Test.php ├── FactoryMethod │ ├── Factory.php │ ├── Factory │ │ ├── Car.php │ │ └── Plane.php │ ├── Product.php │ ├── Product │ │ ├── Car.php │ │ └── Plane.php │ ├── README.md │ └── Test.php ├── Prototype │ ├── Book.php │ ├── Book │ │ ├── MySQL.php │ │ └── PHP.php │ ├── README.md │ └── Test.php ├── README.md └── Singleton │ ├── README.md │ ├── Singleton.php │ └── Test.php ├── README.md ├── Structural ├── Adapter │ ├── README.md │ ├── RectangleLegacy.php │ ├── Shape.php │ ├── Shape │ │ └── Rectangle.php │ └── Test.php ├── Bridge │ ├── Color.php │ ├── Color │ │ ├── Blue.php │ │ ├── Green.php │ │ └── Red.php │ ├── README.md │ ├── Shape.php │ ├── Shape │ │ ├── Circle.php │ │ └── Square.php │ └── Test.php ├── Composite │ ├── README.md │ ├── Test.php │ ├── Text.php │ └── Text │ │ ├── Character.php │ │ ├── Sentence.php │ │ └── Word.php ├── Decorator │ ├── Decorator.php │ ├── Decorator │ │ ├── Border.php │ │ └── Scroll.php │ ├── README.md │ ├── Test.php │ ├── TextField.php │ └── Widget.php ├── Facade │ ├── ComputerFacade.php │ ├── HardDrive.php │ ├── Memory.php │ ├── Processor.php │ ├── README.md │ └── Test.php ├── Flyweight │ ├── Character.php │ ├── CharacterFactory.php │ ├── README.md │ └── Test.php ├── Proxy │ ├── Image.php │ ├── Image │ │ ├── Proxy.php │ │ └── Real.php │ ├── README.md │ └── Test.php └── README.md ├── bootstrap.php ├── composer.json ├── composer.lock ├── phpunit.xml └── ~images ├── AbstractFactory.png ├── Adapter.png ├── B.png ├── BCS.png ├── Bridge.png ├── Builder.png ├── C.png ├── ChainOfResponsibility.png ├── Command.png ├── Composite.png ├── Decorator.png ├── Facade.png ├── FactoryMethod.png ├── Flyweight.png ├── Interpreter.png ├── Iterator.png ├── Mediator.png ├── Memento.png ├── Observer.png ├── Prototype.png ├── Proxy.png ├── S.png ├── Singleton.png ├── State.png ├── Strategy.png ├── TemplateMethod.png ├── Visitor.png ├── aggregation.png ├── composition.png ├── dependency.png ├── generalization.png └── ru ├── AbstractFactory.png ├── Adapter.png ├── BCS.png ├── Bridge.png ├── Builder.png ├── ChainofResponsibility.png ├── Command.png ├── Composite.png ├── Decorator.png ├── Facade.png ├── FactoryMethod.png ├── Flyweight.png ├── Interpreter.png ├── Iterator.png ├── Mediator.png ├── Memento.png ├── Observer.png ├── Prototype.png ├── Proxy.png ├── Singleton.png ├── State.png ├── Strategy.png ├── TemplateMethod.png └── Visitor.png /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | .idea/ -------------------------------------------------------------------------------- /Behavioral/ChainOfResponsobility/Logger.php: -------------------------------------------------------------------------------- 1 | next = $next; 27 | $this->priority = $priority; 28 | } 29 | 30 | 31 | public function message($message, $priority) 32 | { 33 | if($this->priority <= $priority) { 34 | $this->writeMessage($message); 35 | } 36 | 37 | if ($this->next) { 38 | $this->next->message($message, $priority); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Behavioral/ChainOfResponsobility/Logger/Email.php: -------------------------------------------------------------------------------- 1 | successor(new Handler\ConcreteHandler2()); 23 | 24 | $this->assertTrue($handler->handleRequest('request1')); 25 | $this->assertTrue($handler->handleRequest('request2')); 26 | $this->assertFalse($handler->handleRequest('request3')); 27 | ``` 28 | 29 | ## When to Use 30 | - When more than one object may handle a request, and the handler isn't known 31 | - When you want to issue a request to one of several objects without specifying the receiver explicitly 32 | - When the set of objects that can handle a request should be specified dynamically 33 | -------------------------------------------------------------------------------- /Behavioral/ChainOfResponsobility/Test.php: -------------------------------------------------------------------------------- 1 | message('Start profiling module1', LoggerHelper::PRIORITY_DEBUG); 21 | $loger->message('Access denied for User1', LoggerHelper::PRIORITY_NOTICE); 22 | $loger->message('Roll back the transaction', LoggerHelper::PRIORITY_ERROR); 23 | 24 | 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Behavioral/Command/Calculator.php: -------------------------------------------------------------------------------- 1 | result += $operand; 21 | break; 22 | case OperationHelper::OPERATOR_MINUS: 23 | $this->result -= $operand; 24 | break; 25 | case OperationHelper::OPERATOR_MULTIPLICATION: 26 | $this->result *= $operand; 27 | break; 28 | case OperationHelper::OPERATOR_DIVISION: 29 | $this->result /= $operand; 30 | break; 31 | } 32 | } 33 | 34 | /** 35 | * @return int 36 | */ 37 | public function getResult() 38 | { 39 | return $this->result; 40 | } 41 | 42 | 43 | } -------------------------------------------------------------------------------- /Behavioral/Command/Operation.php: -------------------------------------------------------------------------------- 1 | calculator = $calculator; 28 | $this->operand = $operand; 29 | } 30 | 31 | public function execute() 32 | { 33 | $this->calculator->operate($this->operator(), $this->operand); 34 | } 35 | } -------------------------------------------------------------------------------- /Behavioral/Command/Operation/Division.php: -------------------------------------------------------------------------------- 1 | placeOperation(new Plus($calculator, 10)); 24 | $this->assertEquals(10, $calculator->getResult()); 25 | 26 | $window->placeOperation(new Minus($calculator, 4)); 27 | $this->assertEquals(6, $calculator->getResult()); 28 | 29 | $window->placeOperation(new Multiplication($calculator, 3)); 30 | $this->assertEquals(18, $calculator->getResult()); 31 | 32 | $window->placeOperation(new Division($calculator, 2)); 33 | $this->assertEquals(9, $calculator->getResult()); 34 | ``` 35 | 36 | ## When to Use 37 | - When you want to parameterize objects with operations 38 | - When you want to queue operations, schedule their execution, or execute them remotely 39 | - When you need to implement undo/redo functionality 40 | - When you want to structure a system around high-level operations built on primitive operations 41 | - When you need to decouple an object that invokes operations from the objects that actually perform these operations 42 | -------------------------------------------------------------------------------- /Behavioral/Command/Test.php: -------------------------------------------------------------------------------- 1 | placeOperation(new Plus($calculator, 10)); 26 | $this->assertEquals(10, $calculator->getResult()); 27 | 28 | $window->placeOperation(new Minus($calculator, 4)); 29 | $this->assertEquals(6, $calculator->getResult()); 30 | 31 | $window->placeOperation(new Multiplication($calculator, 3)); 32 | $this->assertEquals(18, $calculator->getResult()); 33 | 34 | $window->placeOperation(new Division($calculator, 2)); 35 | $this->assertEquals(9, $calculator->getResult()); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Behavioral/Command/Window.php: -------------------------------------------------------------------------------- 1 | execute(); 19 | $this->commands[] = $operation; 20 | } 21 | } -------------------------------------------------------------------------------- /Behavioral/Interpreter/Context.php: -------------------------------------------------------------------------------- 1 | variables = $variables; 23 | } 24 | 25 | 26 | public function getByName($name) 27 | { 28 | return isset($this->variables[$name]) ? $this->variables[$name]: null; 29 | } 30 | } -------------------------------------------------------------------------------- /Behavioral/Interpreter/Expression.php: -------------------------------------------------------------------------------- 1 | operandLeft = $operandLeft; 28 | $this->operandRight = $operandRight; 29 | } 30 | 31 | public function interpret(Context $context) 32 | { 33 | return $this->operandLeft->interpret($context) - $this->operandRight->interpret($context); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /Behavioral/Interpreter/Expression/Plus.php: -------------------------------------------------------------------------------- 1 | operandLeft = $operandLeft; 29 | $this->operandRight = $operandRight; 30 | } 31 | 32 | public function interpret(Context $context) 33 | { 34 | return $this->operandLeft->interpret($context) + $this->operandRight->interpret($context); 35 | } 36 | } -------------------------------------------------------------------------------- /Behavioral/Interpreter/Expression/Variable.php: -------------------------------------------------------------------------------- 1 | name = $name; 26 | } 27 | 28 | public function interpret(Context $context) 29 | { 30 | return $context->getByName($this->name); 31 | } 32 | } -------------------------------------------------------------------------------- /Behavioral/Interpreter/README.md: -------------------------------------------------------------------------------- 1 | # Interpreter Pattern 2 | 3 | ## Type: Behavioral 4 | 5 | ## Description 6 | Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language. 7 | 8 | ## Structure 9 | ![Interpreter Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Interpreter.png) 10 | 11 | ## Implementation 12 | The example implements the Interpreter pattern to define object behaviors and communication: 13 | 14 | ## Sample Code 15 | 16 | ```php 17 | 18 | // "a b c - +"; 19 | $expression = new Plus( 20 | new Variable("a"), 21 | new Minus( 22 | new Variable("b"), 23 | new Variable("c") 24 | ) 25 | ); 26 | 27 | $context = new Context(["a"=>25, "b"=>6, "c"=>5]); 28 | $result = $expression->interpret($context); 29 | $this->assertEquals(26, $result); 30 | 31 | // "d a b c - + -"; 32 | $expression = new Minus( 33 | new Variable("d"), 34 | new Plus( 35 | new Variable("a"), 36 | new Minus( 37 | new Variable("b"), 38 | new Variable("c") 39 | ) 40 | ) 41 | ); 42 | 43 | $context = new Context(["a"=>25, "b"=>6, "c"=>5, "d"=>30]); 44 | $result = $expression->interpret($context); 45 | $this->assertEquals(4, $result); 46 | ``` 47 | 48 | ## When to Use 49 | - When you need to implement a simple language 50 | - When you have a language to interpret, and you can represent statements as abstract syntax trees 51 | - When the grammar is simple and efficiency is not a critical concern 52 | -------------------------------------------------------------------------------- /Behavioral/Interpreter/Test.php: -------------------------------------------------------------------------------- 1 | 25, "b"=>6, "c"=>5]); 29 | $result = $expression->interpret($context); 30 | $this->assertEquals(26, $result); 31 | 32 | // "d a b c - + -"; 33 | $expression = new Minus( 34 | new Variable("d"), 35 | new Plus( 36 | new Variable("a"), 37 | new Minus( 38 | new Variable("b"), 39 | new Variable("c") 40 | ) 41 | ) 42 | ); 43 | 44 | $context = new Context(["a"=>25, "b"=>6, "c"=>5, "d"=>30]); 45 | $result = $expression->interpret($context); 46 | $this->assertEquals(4, $result); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Behavioral/Iterator/Aggregator.php: -------------------------------------------------------------------------------- 1 | goods = [1, 2, 3]; 24 | } 25 | 26 | public function createIterator() 27 | { 28 | return new \Behavioral\Iterator\Iterator\Shop($this->goods); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /Behavioral/Iterator/Iterator.php: -------------------------------------------------------------------------------- 1 | goods = $goods; 27 | } 28 | 29 | 30 | public function next() 31 | { 32 | $good = null; 33 | 34 | if(isset($this->goods[$this->position])){ 35 | $good = $this->goods[$this->position]; 36 | $this->position++; 37 | } 38 | return $good; 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /Behavioral/Iterator/README.md: -------------------------------------------------------------------------------- 1 | # Iterator Pattern 2 | 3 | ## Type: Behavioral 4 | 5 | ## Description 6 | Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. 7 | 8 | ## Structure 9 | ![Iterator Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Iterator.png) 10 | 11 | ## Implementation 12 | The example implements the Iterator pattern with a shop collection: 13 | - A `Shop` class that acts as an aggregator for a collection of items 14 | - An Iterator interface that defines the traversal methods (`next()`) 15 | - The shop provides a `createIterator()` method to return an appropriate iterator 16 | - The client uses the iterator to access elements without knowing the internal structure 17 | 18 | ## Sample Code 19 | 20 | ```php 21 | $aggregator = new Aggregator\Shop(); 22 | $iterator = $aggregator->createIterator(); 23 | 24 | $this->assertEquals(1, $iterator->next()); 25 | $this->assertEquals(2, $iterator->next()); 26 | $this->assertEquals(3, $iterator->next()); 27 | $this->assertEquals(null, $iterator->next()); 28 | ``` 29 | 30 | ## When to Use 31 | - When you want to access an aggregate object's contents without exposing its internal representation 32 | - When you want to support multiple traversals of aggregate objects 33 | - When you want to provide a uniform interface for traversing different aggregate structures 34 | -------------------------------------------------------------------------------- /Behavioral/Iterator/Test.php: -------------------------------------------------------------------------------- 1 | createIterator(); 18 | 19 | $this->assertEquals(1, $iterator->next()); 20 | $this->assertEquals(2, $iterator->next()); 21 | $this->assertEquals(3, $iterator->next()); 22 | $this->assertEquals(null, $iterator->next()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Behavioral/Mediator/Colleaque.php: -------------------------------------------------------------------------------- 1 | mediator = $mediator; 27 | $this->name = (string)$name; 28 | } 29 | 30 | public function getName(){ 31 | return (string)$this->name; 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /Behavioral/Mediator/Colleque/AuthorBook.php: -------------------------------------------------------------------------------- 1 | $value){ 20 | if($key = "author"){ 21 | $this->name = $value; 22 | } 23 | } 24 | } 25 | 26 | 27 | } -------------------------------------------------------------------------------- /Behavioral/Mediator/Colleque/TitleBook.php: -------------------------------------------------------------------------------- 1 | $value){ 20 | if($key = "title"){ 21 | $this->name = $value; 22 | } 23 | } 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /Behavioral/Mediator/Mediator.php: -------------------------------------------------------------------------------- 1 | title = new TitleBookColleaque($mediator = $this, $name = $title); 29 | $this->author = new AuthorBookColleaque($mediator = $this, $name = $author); 30 | } 31 | 32 | /** 33 | * @return AuthorBookColleaque 34 | */ 35 | public function getAuthor() 36 | { 37 | return $this->author; 38 | } 39 | 40 | /** 41 | * @param AuthorBookColleaque $author 42 | */ 43 | public function setAuthor($authorName) 44 | { 45 | $this->title = $this->author->change(["author"=>(string)$authorName]); 46 | } 47 | 48 | /** 49 | * @return TitleBookColleaque 50 | */ 51 | public function getTitle() 52 | { 53 | return $this->title; 54 | } 55 | 56 | /** 57 | * @param TitleBookColleaque $title 58 | */ 59 | public function setTitle($titleName) 60 | { 61 | $this->title = $this->title->change(["title"=>(string)$titleName]); 62 | } 63 | 64 | 65 | 66 | 67 | } -------------------------------------------------------------------------------- /Behavioral/Mediator/README.md: -------------------------------------------------------------------------------- 1 | # Mediator Pattern 2 | 3 | ## Type: Behavioral 4 | 5 | ## Description 6 | Define an object that encapsulates how a set of objects interact. Promotes loose coupling by keeping objects from referring to each other explicitly and it lets you vary their interactions independently. 7 | 8 | ## Structure 9 | ![Mediator Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Mediator.png) 10 | 11 | ## Implementation 12 | The example implements the Mediator pattern to define object behaviors and communication: 13 | 14 | ## Sample Code 15 | 16 | ```php 17 | 18 | $book = new BookMediator( 19 | $title = "Design Patterns", 20 | $author = "Erich Gamma" 21 | ); 22 | 23 | $title = $book->getTitle(); 24 | $author = $book->getAuthor(); 25 | 26 | $this->assertEquals("Design Patterns", $title->getName()); 27 | $this->assertEquals("Erich Gamma", $author->getName()); 28 | 29 | $book->setTitle("Design Patterns: Elements of Reusable Object-Oriented Software"); 30 | $book->setAuthor("Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides"); 31 | 32 | 33 | $this->assertEquals("Design Patterns: Elements of Reusable Object-Oriented Software", $title->getName()); 34 | $this->assertEquals("Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides", $author->getName()); 35 | ``` 36 | 37 | ## When to Use 38 | - When a set of objects communicate in well-defined but complex ways 39 | - When reusing an object is difficult because it refers to and communicates with many other objects 40 | - When behavior that's distributed between several classes should be customizable without a lot of subclassing 41 | -------------------------------------------------------------------------------- /Behavioral/Mediator/Test.php: -------------------------------------------------------------------------------- 1 | getTitle(); 26 | $author = $book->getAuthor(); 27 | 28 | $this->assertEquals("Design Patterns", $title->getName()); 29 | $this->assertEquals("Erich Gamma", $author->getName()); 30 | 31 | $book->setTitle("Design Patterns: Elements of Reusable Object-Oriented Software"); 32 | $book->setAuthor("Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides"); 33 | 34 | 35 | $this->assertEquals("Design Patterns: Elements of Reusable Object-Oriented Software", $title->getName()); 36 | $this->assertEquals("Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides", $author->getName()); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Behavioral/Memento/Caretaker.php: -------------------------------------------------------------------------------- 1 | memento = $memento; 22 | } 23 | 24 | /** 25 | * @return mixed 26 | */ 27 | public function getMemento() 28 | { 29 | return $this->memento; 30 | } 31 | 32 | 33 | } -------------------------------------------------------------------------------- /Behavioral/Memento/Memento.php: -------------------------------------------------------------------------------- 1 | state = $state; 23 | } 24 | 25 | /** 26 | * @return mixed 27 | */ 28 | public function getState() 29 | { 30 | return $this->state; 31 | } 32 | 33 | 34 | 35 | } -------------------------------------------------------------------------------- /Behavioral/Memento/Originator.php: -------------------------------------------------------------------------------- 1 | state); 19 | } 20 | 21 | public function restore(Memento $memento) 22 | { 23 | $this->state = $memento->getState(); 24 | } 25 | /** 26 | * @param mixed $state 27 | */ 28 | public function setState($state) 29 | { 30 | $this->state = $state; 31 | } 32 | 33 | /** 34 | * @return mixed 35 | */ 36 | public function getState() 37 | { 38 | return $this->state; 39 | } 40 | 41 | 42 | 43 | 44 | } -------------------------------------------------------------------------------- /Behavioral/Memento/README.md: -------------------------------------------------------------------------------- 1 | # Memento Pattern 2 | 3 | ## Type: Behavioral 4 | 5 | ## Description 6 | Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later. 7 | 8 | ## Structure 9 | ![Memento Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Memento.png) 10 | 11 | ## Implementation 12 | The example implements the Memento pattern to define object behaviors and communication: 13 | 14 | ## Sample Code 15 | 16 | ```php 17 | 18 | $originator = new Originator(); 19 | $originator->setState("On"); 20 | 21 | $memento = $originator->createMemento(); 22 | 23 | $caretaker = new Caretaker(); 24 | $caretaker->setMemento($memento); 25 | 26 | $originator->setState('Off'); 27 | 28 | $memento = $caretaker->getMemento(); 29 | 30 | $originator->restore($memento); 31 | ``` 32 | 33 | ## When to Use 34 | - When you need to capture an object's internal state for later restoration 35 | - When a direct interface to obtaining the state would expose implementation details 36 | - When you need to implement checkpoints and an undo mechanism 37 | -------------------------------------------------------------------------------- /Behavioral/Memento/Test.php: -------------------------------------------------------------------------------- 1 | setState("On"); 18 | 19 | $this->assertEquals("On",$originator->getState()); 20 | 21 | $memento = $originator->createMemento(); 22 | 23 | $this->assertInstanceOf('Behavioral\Memento\Memento', $memento); 24 | 25 | $caretaker = new Caretaker(); 26 | $caretaker->setMemento($memento); 27 | 28 | $originator->setState('Off'); 29 | $this->assertEquals("Off",$originator->getState()); 30 | 31 | $memento = $caretaker->getMemento(); 32 | $this->assertInstanceOf('Behavioral\Memento\Memento', $memento); 33 | 34 | $originator->restore($memento); 35 | $this->assertEquals("On",$originator->getState()); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Behavioral/Observer/Observable.php: -------------------------------------------------------------------------------- 1 | observers[] = $observer; 30 | } 31 | 32 | 33 | public function notify() 34 | { 35 | foreach ($this->observers as $observer) { 36 | $observer->update($this); 37 | } 38 | } 39 | 40 | /** 41 | * @return float 42 | */ 43 | public function getTemperature() 44 | { 45 | return $this->temperature; 46 | } 47 | 48 | /** 49 | * @param float $temperature 50 | */ 51 | public function setTemperature($temperature) 52 | { 53 | $this->temperature = (double)$temperature; 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /Behavioral/Observer/Observer.php: -------------------------------------------------------------------------------- 1 | temperature = (double)$observable->getTemperature(); 23 | } 24 | 25 | /** 26 | * @return mixed 27 | */ 28 | public function getTemperature() 29 | { 30 | return $this->temperature; 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /Behavioral/Observer/Observer/WeatherCustomerDelegate.php: -------------------------------------------------------------------------------- 1 | setTemperature(15); 22 | $this->assertEquals(15, $station->getTemperature()); 23 | 24 | $customer1 = new WeatherCustomerObserver(); 25 | $customer2 = new WeatherCustomerObserver(); 26 | 27 | $station->attach($customer1); 28 | $station->attach($customer2); 29 | 30 | $this->assertEquals(null, $customer1->getTemperature()); 31 | $this->assertEquals(null, $customer2->getTemperature()); 32 | 33 | $station->setTemperature(26); 34 | $station->notify(); 35 | 36 | $this->assertEquals(26, $station->getTemperature()); 37 | $this->assertEquals(26, $customer1->getTemperature()); 38 | $this->assertEquals(26, $customer2->getTemperature()); 39 | 40 | $station->setTemperature(10); 41 | $station->notify(); 42 | 43 | $this->assertEquals(10, $station->getTemperature()); 44 | $this->assertEquals(10, $customer1->getTemperature()); 45 | $this->assertEquals(10, $customer2->getTemperature()); 46 | ``` 47 | 48 | ## When to Use 49 | - When changes to one object require changing others, and you don't know how many objects need to be changed 50 | - When an object should be able to notify other objects without making assumptions about those objects 51 | - For establishing loose coupling between objects that interact with each other 52 | - When you need a one-to-many dependency between objects 53 | -------------------------------------------------------------------------------- /Behavioral/Observer/README.ru.md: -------------------------------------------------------------------------------- 1 | # Шаблон Наблюдатель (Observer) 2 | 3 | ## Тип: Поведенческий 4 | 5 | ## Назначение 6 | Определяет зависимость типа "один ко многим" между объектами таким образом, что при изменении состояния одного объекта все зависящие от него объекты оповещаются и обновляются автоматически. 7 | 8 | ## Проблема 9 | Когда состояние объекта изменяется, все зависимые объекты должны быть уведомлены и обновлены соответствующим образом, но без тесной связи между классами субъекта и наблюдателя. 10 | 11 | ## Решение 12 | Выделение функциональности наблюдения в отдельный интерфейс наблюдателя, что позволяет нескольким независимым наблюдателям получать уведомления об изменениях состояния. 13 | 14 | ## Когда использовать 15 | - Когда изменение в одном объекте требует изменения в других, и вы не знаете, сколько объектов нужно изменить 16 | - Когда объект должен уведомлять другие объекты, не делая предположений о том, кто эти объекты 17 | - Когда фреймворк должен быть расширяемым во время выполнения с наблюдателями, которые могут быть присоединены и отсоединены динамически 18 | 19 | ## Структура 20 | ![Наблюдатель](https://github.com/legrch/php-design-patterns/blob/master/~images/ru/Observer.png) 21 | 22 | ## Участники 23 | - **Субъект (Observable)**: Знает своих наблюдателей и предоставляет интерфейс для присоединения и отсоединения наблюдателей. 24 | - **Наблюдатель (Observer)**: Определяет интерфейс обновления для объектов, которые должны быть уведомлены об изменениях. 25 | - **КонкретныйСубъект (ConcreteSubject)**: Хранит состояние, интересующее объекты КонкретныйНаблюдатель, и отправляет уведомление при изменении своего состояния. 26 | - **КонкретныйНаблюдатель (ConcreteObserver)**: Поддерживает ссылку на объект КонкретныйСубъект и реализует интерфейс обновления Наблюдателя. 27 | 28 | ## Пример 29 | 30 | ```php 31 | $station = new WeatherStationObservable(); 32 | $station->setTemperature(15); 33 | $this->assertEquals(15, $station->getTemperature()); 34 | 35 | $customer1 = new WeatherCustomerObserver(); 36 | $customer2 = new WeatherCustomerObserver(); 37 | 38 | $station->attach($customer1); 39 | $station->attach($customer2); 40 | 41 | $this->assertEquals(null, $customer1->getTemperature()); 42 | $this->assertEquals(null, $customer2->getTemperature()); 43 | 44 | $station->setTemperature(26); 45 | $station->notify(); 46 | 47 | $this->assertEquals(26, $station->getTemperature()); 48 | $this->assertEquals(26, $customer1->getTemperature()); 49 | $this->assertEquals(26, $customer2->getTemperature()); 50 | 51 | $station->setTemperature(10); 52 | $station->notify(); 53 | 54 | $this->assertEquals(10, $station->getTemperature()); 55 | $this->assertEquals(10, $customer1->getTemperature()); 56 | $this->assertEquals(10, $customer2->getTemperature()); 57 | ``` 58 | 59 | ## Примеры из реального мира 60 | - Системы управления событиями 61 | - Механизмы подписки в системах обмена сообщениями 62 | - Системы вещания 63 | - Архитектура MVC для обновления представлений 64 | 65 | ## Связанные шаблоны 66 | - **Посредник (Mediator)**: Инкапсулируя сложную семантику обновления, шаблон Наблюдатель можно рассматривать как упрощенный шаблон Посредник. 67 | - **Одиночка (Singleton)**: Субъект (Observable) часто реализуется как Одиночка. -------------------------------------------------------------------------------- /Behavioral/Observer/Test.php: -------------------------------------------------------------------------------- 1 | setTemperature(15); 20 | $this->assertEquals(15, $station->getTemperature()); 21 | 22 | $customer1 = new WeatherCustomerObserver(); 23 | $customer2 = new WeatherCustomerObserver(); 24 | 25 | $station->attach($customer1); 26 | $station->attach($customer2); 27 | 28 | $this->assertEquals(null, $customer1->getTemperature()); 29 | $this->assertEquals(null, $customer2->getTemperature()); 30 | 31 | $station->setTemperature(26); 32 | $station->notify(); 33 | 34 | $this->assertEquals(26, $station->getTemperature()); 35 | $this->assertEquals(26, $customer1->getTemperature()); 36 | $this->assertEquals(26, $customer2->getTemperature()); 37 | 38 | $station->setTemperature(10); 39 | $station->notify(); 40 | 41 | $this->assertEquals(10, $station->getTemperature()); 42 | $this->assertEquals(10, $customer1->getTemperature()); 43 | $this->assertEquals(10, $customer2->getTemperature()); 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Behavioral/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### ![][B] [Behavioral] 3 | - [Chain of Responsibility](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/ChainOfResponsobility) 4 | - [Command](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/Command) 5 | - [Interpreter](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/Interpreter) 6 | - [Iterator](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/Iterator) 7 | - [Mediator](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/Mediator) 8 | - [Memento](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/Memento) 9 | - [Observer](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/Observer) 10 | - [State](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/State) 11 | - [Strategy](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/Strategy) 12 | - [Template Method](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/TemplateMethod) 13 | - [Visitor](https://github.com/legrch/php-design-patterns/tree/master/Behavioral/Visitor) 14 | 15 | [B]: https://github.com/legrch/php-design-patterns/blob/master/~images/B.png 16 | [Behavioral]: https://github.com/legrch/php-design-patterns/tree/master/Behavioral/ 17 | -------------------------------------------------------------------------------- /Behavioral/State/Context.php: -------------------------------------------------------------------------------- 1 | state = $state; 23 | } 24 | 25 | public function request() 26 | { 27 | $this->state->handle($this); 28 | } 29 | 30 | /** 31 | * @return State 32 | */ 33 | public function getState() 34 | { 35 | return $this->state; 36 | } 37 | 38 | /** 39 | * @param State $state 40 | */ 41 | public function setState(State $state) 42 | { 43 | $this->state = $state; 44 | } 45 | 46 | 47 | } -------------------------------------------------------------------------------- /Behavioral/State/README.md: -------------------------------------------------------------------------------- 1 | # State Pattern 2 | 3 | ## Type: Behavioral 4 | 5 | ## Description 6 | Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. 7 | 8 | ## Structure 9 | ![State Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/State.png) 10 | 11 | ## Implementation 12 | The example implements the State pattern to define object behaviors and communication: 13 | 14 | ## Sample Code 15 | 16 | ```php 17 | 18 | $context = new context(new StateA()); 19 | $this->assertInstanceOf('Behavioral\State\State\A', $context->getState()); 20 | 21 | $context->request(); 22 | $this->assertInstanceOf('Behavioral\State\State\B', $context->getState()); 23 | 24 | $context->request(); 25 | $this->assertInstanceOf('Behavioral\State\State\C', $context->getState()); 26 | 27 | $context->request(); 28 | $this->assertInstanceOf('Behavioral\State\State\A', $context->getState()); 29 | ``` 30 | 31 | ## When to Use 32 | - When an object's behavior depends on its state, and it must change its behavior at runtime 33 | - When operations have large, multipart conditional statements that depend on the object's state 34 | - When a context can be in one of many states, with state-specific behavior 35 | -------------------------------------------------------------------------------- /Behavioral/State/State.php: -------------------------------------------------------------------------------- 1 | setState(new B()); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /Behavioral/State/State/B.php: -------------------------------------------------------------------------------- 1 | setState(new C()); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /Behavioral/State/State/C.php: -------------------------------------------------------------------------------- 1 | setState(new A()); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /Behavioral/State/Test.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('Behavioral\State\State\A', $context->getState()); 20 | 21 | $context->request(); 22 | $this->assertInstanceOf('Behavioral\State\State\B', $context->getState()); 23 | 24 | $context->request(); 25 | $this->assertInstanceOf('Behavioral\State\State\C', $context->getState()); 26 | 27 | $context->request(); 28 | $this->assertInstanceOf('Behavioral\State\State\A', $context->getState()); 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Behavioral/Strategy/BillingStrategy.php: -------------------------------------------------------------------------------- 1 | billingStrategy = $billingStrategy; 26 | } 27 | 28 | public function addToBilling($price, $quantity) 29 | { 30 | $this->billing[] = $this->billingStrategy->calc($price * $quantity); 31 | } 32 | 33 | public function sumOfBilling() 34 | { 35 | return array_sum($this->billing); 36 | } 37 | 38 | /** 39 | * @param BillingStrategy $billingStrategy 40 | */ 41 | public function setStrategy(BillingStrategy $billingStrategy) 42 | { 43 | $this->billingStrategy = $billingStrategy; 44 | } 45 | 46 | 47 | } -------------------------------------------------------------------------------- /Behavioral/Strategy/README.md: -------------------------------------------------------------------------------- 1 | # Strategy Pattern 2 | 3 | ## Type: Behavioral 4 | 5 | ## Description 6 | The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. It allows the algorithm to vary independently from clients that use it. 7 | 8 | ## Structure 9 | ![Strategy Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Strategy.png) 10 | 11 | ## Implementation 12 | The example implements the Strategy pattern using different billing strategies: 13 | - A `Customer` class that can use different billing strategies 14 | - Concrete strategy implementations (`NormalBillingStrategy` and `HappyHourBillingStrategy`) 15 | - The ability to switch strategies at runtime 16 | 17 | ## Sample Code 18 | 19 | ```php 20 | $customer = new Customer(new NormalBillingStrategy); 21 | $customer->addToBilling($price=2.5, $quantity=2); 22 | $this->assertEquals(5.0, $customer->sumOfBilling()); 23 | 24 | $customer->setStrategy(new HappyHourBillingStrategy); 25 | $customer->addToBilling($price=2.5, $quantity=4); 26 | $this->assertEquals(10.0, $customer->sumOfBilling()); 27 | ``` 28 | 29 | ## When to Use 30 | - When you need different variants of an algorithm 31 | - When you want to avoid exposing complex algorithm-specific structures 32 | - When an algorithm uses data that clients shouldn't know about 33 | - When a class defines many behaviors that appear as multiple conditional statements 34 | -------------------------------------------------------------------------------- /Behavioral/Strategy/Test.php: -------------------------------------------------------------------------------- 1 | addToBilling($price=2.5, $quantity=2); 22 | $this->assertEquals(5.0, $customer->sumOfBilling()); 23 | 24 | $customer->setStrategy(new HappyHourBillingStrategy); 25 | $customer->addToBilling($price=2.5, $quantity=4); 26 | $this->assertEquals(10.0, $customer->sumOfBilling()); 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Behavioral/TemplateMethod/Game.php: -------------------------------------------------------------------------------- 1 | init(); 17 | $this->start(); 18 | $this->end(); 19 | 20 | return true; 21 | } 22 | 23 | abstract protected function init(); 24 | abstract protected function start(); 25 | abstract protected function end(); 26 | 27 | } -------------------------------------------------------------------------------- /Behavioral/TemplateMethod/Game/Basketball.php: -------------------------------------------------------------------------------- 1 | play(); 21 | $this->assertTrue($result); 22 | 23 | $game = new BasketballGame; 24 | $result = $game->play(); 25 | $this->assertTrue($result); 26 | ``` 27 | 28 | ## When to Use 29 | - When you want to let clients extend only particular steps of an algorithm 30 | - When you have several classes that contain nearly identical algorithms with some minor differences 31 | - When you want to avoid code duplication by moving common behavior to a single class 32 | -------------------------------------------------------------------------------- /Behavioral/TemplateMethod/README.ru.md: -------------------------------------------------------------------------------- 1 | # Шаблонный метод (Template Method) 2 | 3 | ## Тип: Поведенческий (Behavioral) 4 | 5 | ## Описание 6 | Шаблонный метод определяет скелет алгоритма в операции, откладывая определение некоторых шагов до подклассов. Он позволяет подклассам переопределять определенные шаги алгоритма, не изменяя его структуру. 7 | 8 | ## Структура 9 | ![Шаблонный метод](https://github.com/legrch/php-design-patterns/blob/master/~images/ru/TemplateMethod.png) 10 | 11 | ## Реализация 12 | Пример реализует шаблонный метод с использованием игрового сценария: 13 | - Абстрактный класс `Game` определяет шаблонный метод `play()`, который последовательно вызывает три абстрактных метода 14 | - Конкретные подклассы (`FootballGame` и `BasketballGame`) реализуют эти абстрактные методы своим специфическим поведением 15 | 16 | ## Пример кода 17 | 18 | ```php 19 | $game = new FootballGame; 20 | $result = $game->play(); 21 | $this->assertTrue($result); 22 | 23 | $game = new BasketballGame; 24 | $result = $game->play(); 25 | $this->assertTrue($result); 26 | ``` 27 | 28 | ## Когда использовать 29 | - Когда нужно позволить клиентам расширять только определенные шаги алгоритма 30 | - Когда у вас есть несколько классов, содержащих почти идентичные алгоритмы с некоторыми незначительными различиями 31 | - Когда нужно избежать дублирования кода, перемещая общее поведение в единый класс 32 | 33 | [English version / Английская версия](./README.md) -------------------------------------------------------------------------------- /Behavioral/TemplateMethod/Test.php: -------------------------------------------------------------------------------- 1 | play(); 20 | $this->assertTrue($result); 21 | 22 | 23 | $game = new BasketballGame; 24 | $result = $game->play(); 25 | $this->assertTrue($result); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Behavioral/Visitor/Item.php: -------------------------------------------------------------------------------- 1 | name = $name; 28 | $this->price = $price; 29 | } 30 | 31 | /** 32 | * @return mixed 33 | */ 34 | public function getName() 35 | { 36 | return $this->name; 37 | } 38 | 39 | /** 40 | * @return mixed 41 | */ 42 | public function getPrice() 43 | { 44 | return $this->price; 45 | } 46 | 47 | 48 | public function accept(ItemVisitor $visitor) 49 | { 50 | return $visitor->visitBook($this); 51 | } 52 | } -------------------------------------------------------------------------------- /Behavioral/Visitor/Item/Fruit.php: -------------------------------------------------------------------------------- 1 | name = $name; 30 | $this->pricePerKg = $pricePerKg; 31 | $this->weight = $weight; 32 | } 33 | 34 | /** 35 | * @return mixed 36 | */ 37 | public function getName() 38 | { 39 | return $this->name; 40 | } 41 | 42 | /** 43 | * @return mixed 44 | */ 45 | public function getPricePerKg() 46 | { 47 | return $this->pricePerKg; 48 | } 49 | 50 | /** 51 | * @return mixed 52 | */ 53 | public function getWeight() 54 | { 55 | return $this->weight; 56 | } 57 | 58 | 59 | public function accept(itemVisitor $visitor) 60 | { 61 | return $visitor->visitFruit($this); 62 | } 63 | 64 | 65 | 66 | 67 | } -------------------------------------------------------------------------------- /Behavioral/Visitor/ItemVisitor.php: -------------------------------------------------------------------------------- 1 | getPrice(); 21 | 22 | // implement $5 discount 23 | if($price > 20){ 24 | $price -= 5; 25 | } 26 | return $price; 27 | } 28 | 29 | public function visitFruit(Fruit $fruit) 30 | { 31 | return $fruit->getPricePerKg() * $fruit->getWeight(); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /Behavioral/Visitor/README.md: -------------------------------------------------------------------------------- 1 | # Visitor Pattern 2 | 3 | ## Type: Behavioral 4 | 5 | ## Description 6 | Represent an operation to be performed on the elements of an object structure. Lets you define a new operation without changing the classes of the elements on which it operates. 7 | 8 | ## Structure 9 | ![Visitor Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Visitor.png) 10 | 11 | ## Implementation 12 | The example implements the Visitor pattern to define object behaviors and communication: 13 | 14 | ## Sample Code 15 | 16 | ```php 17 | 18 | $visitor = new PriceItemVisitor(); 19 | $item = new BookItem($name = "Im Westen nichts Neues, Erich Maria Remarque", $price = 22.50); 20 | $price = $item->accept($visitor); 21 | $this->assertEquals(17.5, $price); 22 | 23 | $item = new FruitItem($name = "apple", $pricePerKg = 1.5, $weight = 2); 24 | $price = $item->accept($visitor); 25 | $this->assertEquals(3.0, $price); 26 | ``` 27 | 28 | ## When to Use 29 | - When you need to perform operations on all elements of a complex object structure 30 | - When you want to avoid polluting the classes with operations that are only needed for specific operations 31 | - When the classes defining the object structure rarely change, but you often want to define new operations over the structure 32 | -------------------------------------------------------------------------------- /Behavioral/Visitor/Test.php: -------------------------------------------------------------------------------- 1 | accept($visitor); 22 | $this->assertEquals(17.5, $price); 23 | 24 | $item = new FruitItem($name = "apple", $pricePerKg = 1.5, $weight = 2); 25 | $price = $item->accept($visitor); 26 | $this->assertEquals(3.0, $price); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/Book.php: -------------------------------------------------------------------------------- 1 | type; 25 | } 26 | 27 | /** 28 | * @return mixed 29 | */ 30 | public function getName() 31 | { 32 | return $this->name; 33 | } 34 | 35 | /** 36 | * @return mixed 37 | */ 38 | public function getAuthor() 39 | { 40 | return $this->author; 41 | } 42 | 43 | /** 44 | * @return mixed 45 | */ 46 | public function getPublisher() 47 | { 48 | return $this->publisher; 49 | } 50 | 51 | 52 | 53 | 54 | } -------------------------------------------------------------------------------- /Creational/AbstractFactory/Book/MySQL.php: -------------------------------------------------------------------------------- 1 | createPHPBook(); 23 | 24 | $this->assertEquals('php', $book->getType()); 25 | $this->assertEquals(BookHelper::PUBLISHER_PITER, $book->getPublisher()); 26 | 27 | $book = $factory->createMySQLBook(); 28 | 29 | $this->assertEquals('mysql', $book->getType()); 30 | $this->assertEquals(BookHelper::PUBLISHER_PITER, $book->getPublisher()); 31 | 32 | $factory = new BookFactory\Williams(); 33 | $book = $factory->createPHPBook(); 34 | 35 | $this->assertEquals('php', $book->getType()); 36 | $this->assertEquals(BookHelper::PUBLISHER_WILLIAMS, $book->getPublisher()); 37 | 38 | $book = $factory->createMySQLBook(); 39 | 40 | $this->assertEquals('mysql', $book->getType()); 41 | $this->assertEquals(BookHelper::PUBLISHER_WILLIAMS, $book->getPublisher()); 42 | ``` 43 | 44 | ## When to Use 45 | - When a system needs to be independent from the way its products are created 46 | - When a system should be configured with one of multiple families of products 47 | - When you want to provide a class library of products, and you want to reveal just their interfaces, not their implementations 48 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/Test.php: -------------------------------------------------------------------------------- 1 | createPHPBook(); 27 | 28 | $this->assertEquals('php', $book->getType()); 29 | $this->assertEquals(BookHelper::PUBLISHER_PITER, $book->getPublisher()); 30 | 31 | $book = $factory->createMySQLBook(); 32 | 33 | $this->assertEquals('mysql', $book->getType()); 34 | $this->assertEquals(BookHelper::PUBLISHER_PITER, $book->getPublisher()); 35 | } 36 | 37 | public function testWilliamsBookFactory(){ 38 | 39 | $factory = new BookFactory\Williams(); 40 | $book = $factory->createPHPBook(); 41 | 42 | $this->assertEquals('php', $book->getType()); 43 | $this->assertEquals(BookHelper::PUBLISHER_WILLIAMS, $book->getPublisher()); 44 | 45 | $book = $factory->createMySQLBook(); 46 | 47 | $this->assertEquals('mysql', $book->getType()); 48 | $this->assertEquals(BookHelper::PUBLISHER_WILLIAMS, $book->getPublisher()); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /Creational/Builder/Builder.php: -------------------------------------------------------------------------------- 1 | product = new Product(); 22 | } 23 | 24 | public function getProduct() 25 | { 26 | return $this->product; 27 | } 28 | } -------------------------------------------------------------------------------- /Creational/Builder/Builder/Car.php: -------------------------------------------------------------------------------- 1 | product->setName("car"); 19 | } 20 | public function buildPrice() 21 | { 22 | $this->product->setPrice(15000); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /Creational/Builder/Builder/Plane.php: -------------------------------------------------------------------------------- 1 | product->setName("plane"); 19 | } 20 | public function buildPrice() 21 | { 22 | $this->product->setPrice(100500); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /Creational/Builder/Manager.php: -------------------------------------------------------------------------------- 1 | builder = $builder; 23 | } 24 | 25 | public function buildProduct() 26 | { 27 | $this->builder->createProduct(); 28 | $this->builder->buildName(); 29 | $this->builder->buildPrice(); 30 | } 31 | 32 | public function getProduct() 33 | { 34 | return $this->builder->getProduct(); 35 | } 36 | 37 | 38 | } -------------------------------------------------------------------------------- /Creational/Builder/Product.php: -------------------------------------------------------------------------------- 1 | price; 23 | } 24 | 25 | /** 26 | * @param mixed $price 27 | */ 28 | public function setPrice($price) 29 | { 30 | $this->price = $price; 31 | } 32 | /** 33 | * @return mixed 34 | */ 35 | public function getName() 36 | { 37 | return $this->name; 38 | } 39 | 40 | /** 41 | * @param mixed $name 42 | */ 43 | public function setName($name) 44 | { 45 | $this->name = $name; 46 | } 47 | 48 | 49 | } -------------------------------------------------------------------------------- /Creational/Builder/README.md: -------------------------------------------------------------------------------- 1 | # Builder Pattern 2 | 3 | ## Type: Creational 4 | 5 | ## Description 6 | Separate the construction of a complex object from its representing so that the same construction process can create different representations. 7 | 8 | ## Structure 9 | ![Builder Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Builder.png) 10 | 11 | ## Implementation 12 | The example implements the Builder pattern to create objects in a systematic way: 13 | 14 | ## Sample Code 15 | 16 | ```php 17 | 18 | $builder = new Builder\Car(); 19 | $manager = new Manager($builder); 20 | $manager->buildProduct(); 21 | $product = $manager->getProduct(); 22 | 23 | $this->assertEquals("car", $product->getName()); 24 | $this->assertEquals(15000, $product->getPrice()); 25 | 26 | $builder = new Builder\Plane(); 27 | $manager = new Manager($builder); 28 | $manager->buildProduct(); 29 | $product = $manager->getProduct(); 30 | 31 | $this->assertEquals("plane", $product->getName()); 32 | $this->assertEquals(100500, $product->getPrice()); 33 | ``` 34 | 35 | ## When to Use 36 | - When the construction process must allow different representations for the object constructed 37 | - When you need to isolate the code for construction and representation 38 | - When you want to give the client the ability to construct complex objects step by step 39 | -------------------------------------------------------------------------------- /Creational/Builder/Test.php: -------------------------------------------------------------------------------- 1 | buildProduct(); 19 | $product = $manager->getProduct(); 20 | 21 | $this->assertEquals("car", $product->getName()); 22 | $this->assertEquals(15000, $product->getPrice()); 23 | } 24 | public function testProductPlane(){ 25 | $builder = new Builder\Plane(); 26 | $manager = new Manager($builder); 27 | $manager->buildProduct(); 28 | $product = $manager->getProduct(); 29 | 30 | $this->assertEquals("plane", $product->getName()); 31 | $this->assertEquals(100500, $product->getPrice()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Creational/FactoryMethod/Factory.php: -------------------------------------------------------------------------------- 1 | name; 21 | } 22 | 23 | /** 24 | * @param mixed $name 25 | */ 26 | public function setName($name) 27 | { 28 | $this->name = $name; 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /Creational/FactoryMethod/Product/Car.php: -------------------------------------------------------------------------------- 1 | instance(); 19 | $this->assertInstanceOf('Creational\FactoryMethod\Product\Plane', $factory); 20 | 21 | $factory = (new Factory\Car())->instance(); 22 | $this->assertInstanceOf('Creational\FactoryMethod\Product\Car', $factory); 23 | ``` 24 | 25 | ## When to Use 26 | - When a class can't anticipate the type of objects it must create 27 | - When a class wants its subclasses to specify the objects it creates 28 | - When you want to localize the knowledge of which class gets created 29 | -------------------------------------------------------------------------------- /Creational/FactoryMethod/Test.php: -------------------------------------------------------------------------------- 1 | instance(); 16 | $this->assertInstanceOf('Creational\FactoryMethod\Product\Plane', $product); 17 | 18 | $product = (new Factory\Car())->instance(); 19 | $this->assertInstanceOf('Creational\FactoryMethod\Product\Car', $product); 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Creational/Prototype/Book.php: -------------------------------------------------------------------------------- 1 | name; 24 | } 25 | 26 | /** 27 | * @param mixed $name 28 | */ 29 | public function setName($name) 30 | { 31 | $this->name = $name; 32 | } 33 | 34 | /** 35 | * @return mixed 36 | */ 37 | public function getType() 38 | { 39 | return $this->type; 40 | } 41 | 42 | /** 43 | * @param mixed $type 44 | */ 45 | public function setType($type) 46 | { 47 | $this->type = $type; 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /Creational/Prototype/Book/MySQL.php: -------------------------------------------------------------------------------- 1 | assertEquals($prototype, $clone); 22 | $this->assertTrue($prototype !== $clone); 23 | ``` 24 | 25 | ## When to Use 26 | - When a system should be independent of how its products are created 27 | - When you need to avoid building a class hierarchy of factories that parallels the class hierarchy of products 28 | - When instances of a class can have one of only a few different combinations of state 29 | -------------------------------------------------------------------------------- /Creational/Prototype/Test.php: -------------------------------------------------------------------------------- 1 | assertEquals($prototype, $clone); 21 | $this->assertTrue($prototype !== $clone); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Creational/README.md: -------------------------------------------------------------------------------- 1 | ### ![][C] [Creational] 2 | - [Abstract Factory](https://github.com/legrch/php-design-patterns/tree/master/Creational/AbstractFactory) 3 | - [Builder](https://github.com/legrch/php-design-patterns/tree/master/Creational/Builder) 4 | - [Factory Method](https://github.com/legrch/php-design-patterns/tree/master/Creational/FactoryMethod) 5 | - [Prototype](https://github.com/legrch/php-design-patterns/tree/master/Creational/Prototype) 6 | - [Singleton](https://github.com/legrch/php-design-patterns/tree/master/Creational/Singleton) 7 | 8 | [C]: https://github.com/legrch/php-design-patterns/blob/master/~images/C.png 9 | [Creational]: https://github.com/legrch/php-design-patterns/tree/master/Creational/ 10 | -------------------------------------------------------------------------------- /Creational/Singleton/README.md: -------------------------------------------------------------------------------- 1 | # Singleton Pattern 2 | 3 | ## Type: Creational 4 | 5 | ## Description 6 | The Singleton pattern ensures a class only has one instance and provides a global point of access to it. 7 | 8 | ## Structure 9 | ![Singleton Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Singleton.png) 10 | 11 | ## Implementation 12 | The example implements the Singleton pattern: 13 | - A `Singleton` class with a private constructor to prevent direct instantiation 14 | - A static method `instance()` that returns the single instance, creating it if necessary 15 | - The instance is stored in a static variable 16 | 17 | ## Sample Code 18 | 19 | ```php 20 | $singleton = Singleton::instance(); 21 | $singleton2 = Singleton::instance(); 22 | $this->assertTrue($singleton===$singleton2); 23 | ``` 24 | 25 | ## When to Use 26 | - When exactly one instance of a class is needed throughout the application 27 | - When you need stricter control over global variables 28 | - When you want to avoid creating a global variable but still need global access 29 | - When you need to coordinate actions across the system 30 | 31 | ## Considerations 32 | - The pattern can make the code harder to test 33 | - It introduces global state into the application 34 | - Thread safety must be ensured in multithreaded environments 35 | -------------------------------------------------------------------------------- /Creational/Singleton/Singleton.php: -------------------------------------------------------------------------------- 1 | assertTrue($singleton===$singleton2); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Design Patterns in PHP 2 | 3 | This repository contains examples of common design patterns implemented in PHP. 4 | 5 | | ![Behavioral](~images/B.png) [Behavioral](Behavioral/) | ![Creational](~images/C.png) [Creational](Creational/) | ![Structural](~images/S.png) [Structural](Structural/) | 6 | | ------------- | ------------- | ------------- | 7 | | [Chain of Responsibility](Behavioral/ChainOfResponsobility/) | [Abstract Factory](Creational/AbstractFactory/) | [Adapter](Structural/Adapter/) | 8 | | [Command](Behavioral/Command/) | [Builder](Creational/Builder/) | [Bridge](Structural/Bridge/) | 9 | | [Interpreter](Behavioral/Interpreter/) | [Factory Method](Creational/FactoryMethod/) | [Composite](Structural/Composite/) | 10 | | [Iterator](Behavioral/Iterator/) | [Prototype](Creational/Prototype/) | [Decorator](Structural/Decorator/) | 11 | | [Mediator](Behavioral/Mediator/) | [Singleton](Creational/Singleton/) | [Facade](Structural/Facade/) | 12 | | [Memento](Behavioral/Memento/) | | [Flyweight](Structural/Flyweight/) | 13 | | [Observer](Behavioral/Observer/) | | [Proxy](Structural/Proxy/) | 14 | | [State](Behavioral/State/) | | | 15 | | [Strategy](Behavioral/Strategy/) | | | 16 | | [Template Method](Behavioral/TemplateMethod/) | | | 17 | | [Visitor](Behavioral/Visitor/) | | | 18 | 19 | ![Design Patterns Categories](~images/BCS.png) 20 | 21 | ## Class Relationships 22 | 23 | The following relationship types are used in the UML diagrams throughout this repository: 24 | 25 | ![Aggregation](~images/aggregation.png) **Aggregation** - Describes a "whole-part" relationship where the "part" can exist independently of the "whole". The diamond is placed on the "whole" side. 26 | 27 | ![Composition](~images/composition.png) **Composition** - A subtype of aggregation in which the "parts" cannot exist separately from the "whole". 28 | 29 | ![Dependency](~images/dependency.png) **Dependency** - A dashed arrowhead line indicates a class that instantiates objects of another class. The arrow points to the class of the instantiated objects. 30 | 31 | ![Generalization](~images/generalization.png) **Generalization** - Represents inheritance or interface implementation relationships. The arrow points to the superclass or interface. 32 | 33 | ## Installation and Testing 34 | 35 | 1. Clone the repository 36 | 2. Run `composer install` 37 | 3. Execute tests with `vendor/bin/phpunit` 38 | 39 | 40 | ## License 41 | 42 | This project is licensed under the MIT License - see the LICENSE file for details. 43 | 44 | -------------------------------------------------------------------------------- /Structural/Adapter/README.md: -------------------------------------------------------------------------------- 1 | # Adapter Pattern 2 | 3 | ## Type: Structural 4 | 5 | ## Description 6 | The Adapter pattern converts the interface of a class into another interface that clients expect. It allows classes to work together that couldn't otherwise because of incompatible interfaces. 7 | 8 | ## Structure 9 | ![Adapter Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Adapter.png) 10 | 11 | ## Implementation 12 | The example implements the Adapter pattern: 13 | - A `RectangleLegacy` class with an incompatible interface 14 | - A `RectangleShapeAdapter` that adapts the legacy rectangle to a new interface 15 | - The adapter translates calls from the client to the adaptee (legacy object) 16 | 17 | ## Sample Code 18 | 19 | ```php 20 | $rectangle = new RectangleShapeAdapter(new RectangleLegacy()); 21 | $result = $rectangle->display($x1=10, $y1=10, $x2=20, $y2=20); 22 | $this->assertTrue($result); 23 | ``` 24 | 25 | ## When to Use 26 | - When you want to use an existing class, but its interface doesn't match what you need 27 | - When you want to create a reusable class that cooperates with classes that don't necessarily have compatible interfaces 28 | - When you need to use several existing subclasses but it's impractical to adapt their interface by subclassing each one 29 | - When you need to make components work together that weren't designed to work together 30 | - When you need to integrate components from different libraries or frameworks 31 | -------------------------------------------------------------------------------- /Structural/Adapter/RectangleLegacy.php: -------------------------------------------------------------------------------- 1 | adaptee = $adaptee; 32 | } 33 | 34 | /** 35 | * @param $x1 36 | * @param $y1 37 | * @param $x2 38 | * @param $y2 39 | * @return bool 40 | */ 41 | public function display($x1, $y1, $x2, $y2) 42 | { 43 | $w = $x2 - $x1; 44 | $h = $y2 - $y1; 45 | 46 | return $this->adaptee->display($x1, $y1, $w, $h); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /Structural/Adapter/Test.php: -------------------------------------------------------------------------------- 1 | display($x1=10, $y1=10, $x2=20, $y2=20); 20 | $this->assertTrue($result); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Structural/Bridge/Color.php: -------------------------------------------------------------------------------- 1 | code(); 18 | } 19 | } -------------------------------------------------------------------------------- /Structural/Bridge/Color/Blue.php: -------------------------------------------------------------------------------- 1 | applyColor(); 20 | $this->assertEquals('#00FF00', $result); 21 | 22 | $circle = new SquareShape(new RedColor()); 23 | $result =$circle->applyColor(); 24 | $this->assertEquals('#FF0000', $result); 25 | ``` 26 | 27 | ## When to Use 28 | - When you want to avoid a permanent binding between an abstraction and its implementation 29 | - When both the abstractions and their implementations should be extensible through subclasses 30 | - When changes in the implementation should not impact the client code 31 | -------------------------------------------------------------------------------- /Structural/Bridge/Shape.php: -------------------------------------------------------------------------------- 1 | color = $color; 23 | } 24 | 25 | abstract public function applyColor(); 26 | } -------------------------------------------------------------------------------- /Structural/Bridge/Shape/Circle.php: -------------------------------------------------------------------------------- 1 | color->applyColor(); 20 | } 21 | } -------------------------------------------------------------------------------- /Structural/Bridge/Shape/Square.php: -------------------------------------------------------------------------------- 1 | color->applyColor(); 20 | } 21 | } -------------------------------------------------------------------------------- /Structural/Bridge/Test.php: -------------------------------------------------------------------------------- 1 | applyColor(); 21 | $this->assertEquals('#00FF00', $result); 22 | 23 | $circle = new SquareShape(new RedColor()); 24 | $result =$circle->applyColor(); 25 | $this->assertEquals('#FF0000', $result); 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Structural/Composite/README.md: -------------------------------------------------------------------------------- 1 | # Composite Pattern 2 | 3 | ## Type: Structural 4 | 5 | ## Description 6 | Convert the interface of a class into another interface clients expect. Lets classes work together that couldn't otherwise because of incompatible interfaces. 7 | 8 | ## Structure 9 | ![Composite Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Composite.png) 10 | 11 | ## Implementation 12 | The example implements the Composite pattern to organize classes and objects: 13 | 14 | ## Sample Code 15 | 16 | ```php 17 | 18 | $sentence = new Sentence(); 19 | 20 | $wHello = new Word(); 21 | $wHello->add(new Character('H')); 22 | $wHello->add(new Character('e')); 23 | $wHello->add(new Character('l')); 24 | $wHello->add(new Character('l')); 25 | $wHello->add(new Character('o')); 26 | 27 | $sentence->add($wHello); 28 | 29 | $sentence->add(new Character(',')); 30 | $sentence->add(new Character(' ')); 31 | 32 | $wWorld = new Word(); 33 | 34 | $wWorld->add(new Character('w')); 35 | $wWorld->add(new Character('o')); 36 | $wWorld->add(new Character('r')); 37 | $wWorld->add(new Character('l')); 38 | $wWorld->add(new Character('d')); 39 | 40 | $sentence->add($wWorld); 41 | $sentence->add(new Character('!')); 42 | 43 | $this->assertEquals('Hello, world!', $sentence->display()); 44 | ``` 45 | 46 | ## When to Use 47 | - When you want to represent part-whole hierarchies of objects 48 | - When you want clients to be able to ignore the difference between compositions of objects and individual objects 49 | - When the structure can have any level of complexity 50 | -------------------------------------------------------------------------------- /Structural/Composite/Test.php: -------------------------------------------------------------------------------- 1 | add(new Character('H')); 23 | $wHello->add(new Character('e')); 24 | $wHello->add(new Character('l')); 25 | $wHello->add(new Character('l')); 26 | $wHello->add(new Character('o')); 27 | 28 | $sentence->add($wHello); 29 | $sentence->add(new Character(',')); 30 | $sentence->add(new Character(' ')); 31 | 32 | $wWorld = new Word(); 33 | $wWorld->add(new Character('w')); 34 | $wWorld->add(new Character('o')); 35 | $wWorld->add(new Character('r')); 36 | $wWorld->add(new Character('l')); 37 | $wWorld->add(new Character('d')); 38 | 39 | $sentence->add($wWorld); 40 | 41 | $sentence->add(new Character('!')); 42 | 43 | $this->assertEquals('Hello, world!', $sentence->display()); 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Structural/Composite/Text.php: -------------------------------------------------------------------------------- 1 | name = $name; 25 | } 26 | 27 | 28 | public function add(Text $text) 29 | { 30 | throw new \Exception("I can't append child to myself"); 31 | } 32 | 33 | public function display() 34 | { 35 | return $this->name; 36 | } 37 | } -------------------------------------------------------------------------------- /Structural/Composite/Text/Sentence.php: -------------------------------------------------------------------------------- 1 | items[] = $text; 22 | } 23 | 24 | public function display() 25 | { 26 | $text = ''; 27 | 28 | foreach($this->items as $item){ 29 | $text.=$item->display(); 30 | } 31 | 32 | return $text; 33 | } 34 | } -------------------------------------------------------------------------------- /Structural/Composite/Text/Word.php: -------------------------------------------------------------------------------- 1 | widget = $widget; 23 | } 24 | 25 | public function draw() 26 | { 27 | return $this->widget->draw(); 28 | } 29 | } -------------------------------------------------------------------------------- /Structural/Decorator/Decorator/Border.php: -------------------------------------------------------------------------------- 1 | draw(); 24 | $this->assertTrue($result); 25 | ``` 26 | 27 | ## When to Use 28 | - When you need to add responsibilities to objects dynamically without affecting other objects 29 | - When extension by subclassing is impractical or impossible 30 | - When you want to add functionality to an object without changing its interface 31 | -------------------------------------------------------------------------------- /Structural/Decorator/Test.php: -------------------------------------------------------------------------------- 1 | draw(); 24 | $this->assertTrue($result); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Structural/Decorator/TextField.php: -------------------------------------------------------------------------------- 1 | height = (int)$height; 25 | $this->width = (int)$width; 26 | } 27 | 28 | public function draw() 29 | { 30 | printf("Draw Text Field[width:%d, height:%d]\n", $this->width, $this->height); 31 | return true; 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /Structural/Decorator/Widget.php: -------------------------------------------------------------------------------- 1 | hd = new HardDrive(); 28 | $this->processor = new Processor(); 29 | $this->memory = new Memory(); 30 | } 31 | 32 | public function start() 33 | { 34 | $this->processor->freeze(); 35 | $data = $this->hd->read($lba = self::BOOT_SECTOR, $size = self::SECTOR_SIZE); 36 | $this->memory->load( 37 | $position = self::BOOT_ADDRESS, 38 | $data 39 | ); 40 | $this->processor->jumpTo($position = self::BOOT_ADDRESS); 41 | $this->processor->execute(); 42 | return $this; 43 | } 44 | } -------------------------------------------------------------------------------- /Structural/Facade/HardDrive.php: -------------------------------------------------------------------------------- 1 | start(); 20 | $this->assertNotEmpty($result); 21 | 22 | --- 23 | Facade::start(): 24 | 25 | $this->processor->freeze(); 26 | $data = $this->hd->read($lba = self::BOOT_SECTOR, $size = self::SECTOR_SIZE); 27 | $this->memory->load( 28 | $position = self::BOOT_ADDRESS, 29 | $data 30 | ); 31 | $this->processor->jumpTo($position = self::BOOT_ADDRESS); 32 | $this->processor->execute(); 33 | ``` 34 | 35 | ## When to Use 36 | - When you want to provide a simple interface to a complex subsystem 37 | - When there are many dependencies between clients and implementation classes 38 | - When you want to layer your subsystems 39 | -------------------------------------------------------------------------------- /Structural/Facade/Test.php: -------------------------------------------------------------------------------- 1 | start(); 18 | $this->assertNotEmpty($result); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Structural/Flyweight/Character.php: -------------------------------------------------------------------------------- 1 | name = $name; 23 | } 24 | 25 | /** 26 | * @return mixed 27 | */ 28 | public function getName() 29 | { 30 | return $this->name; 31 | } 32 | 33 | 34 | 35 | } -------------------------------------------------------------------------------- /Structural/Flyweight/CharacterFactory.php: -------------------------------------------------------------------------------- 1 | characters)){ 19 | $this->characters[$name] = new Character($name); 20 | } 21 | return $this->characters[$name]; 22 | } 23 | } -------------------------------------------------------------------------------- /Structural/Flyweight/README.md: -------------------------------------------------------------------------------- 1 | # Flyweight Pattern 2 | 3 | ## Type: Structural 4 | 5 | ## Description 6 | Use sharing to support large numbers of fine grained objects efficiently. 7 | 8 | ## Structure 9 | ![Flyweight Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Flyweight.png) 10 | 11 | ## Implementation 12 | The example implements the Flyweight pattern to organize classes and objects: 13 | 14 | ## Sample Code 15 | 16 | ```php 17 | 18 | $factory = new CharacterFactoryFlyweight(); 19 | $character1 = $factory->findCharacter('A'); 20 | $character2 = $factory->findCharacter('A'); 21 | $character3 = $factory->findCharacter('B'); 22 | 23 | $this->assertInstanceOf('Structural\Flyweight\Character', $character1); 24 | $this->assertInstanceOf('Structural\Flyweight\Character', $character2); 25 | $this->assertInstanceOf('Structural\Flyweight\Character', $character3); 26 | 27 | $this->assertTrue($character1 === $character2); 28 | $this->assertFalse($character1 === $character3); 29 | ``` 30 | 31 | ## When to Use 32 | - When an application uses a large number of objects that have some shared state 33 | - When the storage costs are high because of the quantity of objects 34 | - When most object state can be made extrinsic 35 | -------------------------------------------------------------------------------- /Structural/Flyweight/Test.php: -------------------------------------------------------------------------------- 1 | findCharacter('A'); 20 | $character2 = $factory->findCharacter('A'); 21 | $character3 = $factory->findCharacter('B'); 22 | 23 | $this->assertInstanceOf('Structural\Flyweight\Character', $character1); 24 | $this->assertInstanceOf('Structural\Flyweight\Character', $character2); 25 | $this->assertInstanceOf('Structural\Flyweight\Character', $character3); 26 | 27 | $this->assertTrue($character1 === $character2); 28 | $this->assertFalse($character1 === $character3); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Structural/Proxy/Image.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 27 | } 28 | 29 | public function display() 30 | { 31 | if(null == $this->image){ 32 | $this->image = new RealImage($this->filename); 33 | } 34 | 35 | return $this->image->display(); 36 | } 37 | 38 | /** 39 | * @return mixed 40 | */ 41 | public function getImage() 42 | { 43 | return $this->image; 44 | } 45 | 46 | 47 | } -------------------------------------------------------------------------------- /Structural/Proxy/Image/Real.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 25 | } 26 | 27 | 28 | public function display() 29 | { 30 | printf("Displaying real image: %s", $this->filename); 31 | return true; 32 | } 33 | } -------------------------------------------------------------------------------- /Structural/Proxy/README.md: -------------------------------------------------------------------------------- 1 | # Proxy Pattern 2 | 3 | ## Type: Structural 4 | 5 | ## Description 6 | Provide a surrogate or placeholder for another object to control access to it. 7 | 8 | ## Structure 9 | ![Proxy Pattern](https://github.com/legrch/php-design-patterns/blob/master/~images/Proxy.png) 10 | 11 | ## Implementation 12 | The example implements the Proxy pattern to organize classes and objects: 13 | 14 | ## Sample Code 15 | 16 | ```php 17 | 18 | $image = new ProxyImage('photo_10000.jpg'); 19 | 20 | $this->assertInstanceOf('Structural\Proxy\Image\Proxy', $image); 21 | $this->assertNull($image->getImage()); 22 | 23 | $result = $image->display(); 24 | 25 | $this->assertTrue($result); 26 | $this->assertInstanceOf('Structural\Proxy\Image\Real', $image->getImage()); 27 | ``` 28 | 29 | ## When to Use 30 | - When you need a more versatile or sophisticated reference to an object than a simple pointer 31 | - When you want to control access to an object 32 | - When you need to add functionality when accessing an object 33 | -------------------------------------------------------------------------------- /Structural/Proxy/Test.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('Structural\Proxy\Image\Proxy', $image); 21 | $this->assertNull($image->getImage()); 22 | 23 | $result = $image->display(); 24 | 25 | $this->assertTrue($result); 26 | $this->assertInstanceOf('Structural\Proxy\Image\Real', $image->getImage()); 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Structural/README.md: -------------------------------------------------------------------------------- 1 | ### ![][S] [Structural] 2 | - [Adapter](https://github.com/legrch/php-design-patterns/tree/master/Structural/Adapter) 3 | - [Bridge](https://github.com/legrch/php-design-patterns/tree/master/Structural/Bridge) 4 | - [Composite](https://github.com/legrch/php-design-patterns/tree/master/Structural/Composite) 5 | - [Decorator](https://github.com/legrch/php-design-patterns/tree/master/Structural/Decorator) 6 | - [Facade](https://github.com/legrch/php-design-patterns/tree/master/Structural/Facade) 7 | - [Flyweight](https://github.com/legrch/php-design-patterns/tree/master/Structural/Flyweight) 8 | - [Proxy](https://github.com/legrch/php-design-patterns/tree/master/Structural/Proxy) 9 | 10 | [S]: https://github.com/legrch/php-design-patterns/blob/master/~images/S.png 11 | [Structural]: https://github.com/legrch/php-design-patterns/tree/master/Structural/ 12 | -------------------------------------------------------------------------------- /bootstrap.php: -------------------------------------------------------------------------------- 1 | =5.5" 125 | }, 126 | "require-dev": { 127 | "phpunit/phpunit": "^4.6" 128 | }, 129 | "type": "library", 130 | "extra": { 131 | "branch-alias": { 132 | "dev-master": "1.0.x-dev" 133 | } 134 | }, 135 | "autoload": { 136 | "psr-4": { 137 | "phpDocumentor\\Reflection\\": [ 138 | "src" 139 | ] 140 | } 141 | }, 142 | "notification-url": "https://packagist.org/downloads/", 143 | "license": [ 144 | "MIT" 145 | ], 146 | "authors": [ 147 | { 148 | "name": "Jaap van Otterdijk", 149 | "email": "opensource@ijaap.nl" 150 | } 151 | ], 152 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 153 | "homepage": "http://www.phpdoc.org", 154 | "keywords": [ 155 | "FQSEN", 156 | "phpDocumentor", 157 | "phpdoc", 158 | "reflection", 159 | "static analysis" 160 | ], 161 | "time": "2017-09-11 18:02:19" 162 | }, 163 | { 164 | "name": "phpdocumentor/reflection-docblock", 165 | "version": "4.3.0", 166 | "source": { 167 | "type": "git", 168 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 169 | "reference": "94fd0001232e47129dd3504189fa1c7225010d08" 170 | }, 171 | "dist": { 172 | "type": "zip", 173 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", 174 | "reference": "94fd0001232e47129dd3504189fa1c7225010d08", 175 | "shasum": "" 176 | }, 177 | "require": { 178 | "php": "^7.0", 179 | "phpdocumentor/reflection-common": "^1.0.0", 180 | "phpdocumentor/type-resolver": "^0.4.0", 181 | "webmozart/assert": "^1.0" 182 | }, 183 | "require-dev": { 184 | "doctrine/instantiator": "~1.0.5", 185 | "mockery/mockery": "^1.0", 186 | "phpunit/phpunit": "^6.4" 187 | }, 188 | "type": "library", 189 | "extra": { 190 | "branch-alias": { 191 | "dev-master": "4.x-dev" 192 | } 193 | }, 194 | "autoload": { 195 | "psr-4": { 196 | "phpDocumentor\\Reflection\\": [ 197 | "src/" 198 | ] 199 | } 200 | }, 201 | "notification-url": "https://packagist.org/downloads/", 202 | "license": [ 203 | "MIT" 204 | ], 205 | "authors": [ 206 | { 207 | "name": "Mike van Riel", 208 | "email": "me@mikevanriel.com" 209 | } 210 | ], 211 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 212 | "time": "2017-11-30 07:14:17" 213 | }, 214 | { 215 | "name": "phpdocumentor/type-resolver", 216 | "version": "0.4.0", 217 | "source": { 218 | "type": "git", 219 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 220 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 221 | }, 222 | "dist": { 223 | "type": "zip", 224 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 225 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 226 | "shasum": "" 227 | }, 228 | "require": { 229 | "php": "^5.5 || ^7.0", 230 | "phpdocumentor/reflection-common": "^1.0" 231 | }, 232 | "require-dev": { 233 | "mockery/mockery": "^0.9.4", 234 | "phpunit/phpunit": "^5.2||^4.8.24" 235 | }, 236 | "type": "library", 237 | "extra": { 238 | "branch-alias": { 239 | "dev-master": "1.0.x-dev" 240 | } 241 | }, 242 | "autoload": { 243 | "psr-4": { 244 | "phpDocumentor\\Reflection\\": [ 245 | "src/" 246 | ] 247 | } 248 | }, 249 | "notification-url": "https://packagist.org/downloads/", 250 | "license": [ 251 | "MIT" 252 | ], 253 | "authors": [ 254 | { 255 | "name": "Mike van Riel", 256 | "email": "me@mikevanriel.com" 257 | } 258 | ], 259 | "time": "2017-07-14 14:27:02" 260 | }, 261 | { 262 | "name": "phpspec/prophecy", 263 | "version": "1.7.6", 264 | "source": { 265 | "type": "git", 266 | "url": "https://github.com/phpspec/prophecy.git", 267 | "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" 268 | }, 269 | "dist": { 270 | "type": "zip", 271 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", 272 | "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", 273 | "shasum": "" 274 | }, 275 | "require": { 276 | "doctrine/instantiator": "^1.0.2", 277 | "php": "^5.3|^7.0", 278 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", 279 | "sebastian/comparator": "^1.1|^2.0|^3.0", 280 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 281 | }, 282 | "require-dev": { 283 | "phpspec/phpspec": "^2.5|^3.2", 284 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" 285 | }, 286 | "type": "library", 287 | "extra": { 288 | "branch-alias": { 289 | "dev-master": "1.7.x-dev" 290 | } 291 | }, 292 | "autoload": { 293 | "psr-0": { 294 | "Prophecy\\": "src/" 295 | } 296 | }, 297 | "notification-url": "https://packagist.org/downloads/", 298 | "license": [ 299 | "MIT" 300 | ], 301 | "authors": [ 302 | { 303 | "name": "Konstantin Kudryashov", 304 | "email": "ever.zet@gmail.com", 305 | "homepage": "http://everzet.com" 306 | }, 307 | { 308 | "name": "Marcello Duarte", 309 | "email": "marcello.duarte@gmail.com" 310 | } 311 | ], 312 | "description": "Highly opinionated mocking framework for PHP 5.3+", 313 | "homepage": "https://github.com/phpspec/prophecy", 314 | "keywords": [ 315 | "Double", 316 | "Dummy", 317 | "fake", 318 | "mock", 319 | "spy", 320 | "stub" 321 | ], 322 | "time": "2018-04-18 13:57:24" 323 | }, 324 | { 325 | "name": "phpunit/php-code-coverage", 326 | "version": "4.0.8", 327 | "source": { 328 | "type": "git", 329 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 330 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" 331 | }, 332 | "dist": { 333 | "type": "zip", 334 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 335 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 336 | "shasum": "" 337 | }, 338 | "require": { 339 | "ext-dom": "*", 340 | "ext-xmlwriter": "*", 341 | "php": "^5.6 || ^7.0", 342 | "phpunit/php-file-iterator": "^1.3", 343 | "phpunit/php-text-template": "^1.2", 344 | "phpunit/php-token-stream": "^1.4.2 || ^2.0", 345 | "sebastian/code-unit-reverse-lookup": "^1.0", 346 | "sebastian/environment": "^1.3.2 || ^2.0", 347 | "sebastian/version": "^1.0 || ^2.0" 348 | }, 349 | "require-dev": { 350 | "ext-xdebug": "^2.1.4", 351 | "phpunit/phpunit": "^5.7" 352 | }, 353 | "suggest": { 354 | "ext-xdebug": "^2.5.1" 355 | }, 356 | "type": "library", 357 | "extra": { 358 | "branch-alias": { 359 | "dev-master": "4.0.x-dev" 360 | } 361 | }, 362 | "autoload": { 363 | "classmap": [ 364 | "src/" 365 | ] 366 | }, 367 | "notification-url": "https://packagist.org/downloads/", 368 | "license": [ 369 | "BSD-3-Clause" 370 | ], 371 | "authors": [ 372 | { 373 | "name": "Sebastian Bergmann", 374 | "email": "sb@sebastian-bergmann.de", 375 | "role": "lead" 376 | } 377 | ], 378 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 379 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 380 | "keywords": [ 381 | "coverage", 382 | "testing", 383 | "xunit" 384 | ], 385 | "time": "2017-04-02 07:44:40" 386 | }, 387 | { 388 | "name": "phpunit/php-file-iterator", 389 | "version": "1.4.5", 390 | "source": { 391 | "type": "git", 392 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 393 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" 394 | }, 395 | "dist": { 396 | "type": "zip", 397 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", 398 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", 399 | "shasum": "" 400 | }, 401 | "require": { 402 | "php": ">=5.3.3" 403 | }, 404 | "type": "library", 405 | "extra": { 406 | "branch-alias": { 407 | "dev-master": "1.4.x-dev" 408 | } 409 | }, 410 | "autoload": { 411 | "classmap": [ 412 | "src/" 413 | ] 414 | }, 415 | "notification-url": "https://packagist.org/downloads/", 416 | "license": [ 417 | "BSD-3-Clause" 418 | ], 419 | "authors": [ 420 | { 421 | "name": "Sebastian Bergmann", 422 | "email": "sb@sebastian-bergmann.de", 423 | "role": "lead" 424 | } 425 | ], 426 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 427 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 428 | "keywords": [ 429 | "filesystem", 430 | "iterator" 431 | ], 432 | "time": "2017-11-27 13:52:08" 433 | }, 434 | { 435 | "name": "phpunit/php-text-template", 436 | "version": "1.2.1", 437 | "source": { 438 | "type": "git", 439 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 440 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 441 | }, 442 | "dist": { 443 | "type": "zip", 444 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 445 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 446 | "shasum": "" 447 | }, 448 | "require": { 449 | "php": ">=5.3.3" 450 | }, 451 | "type": "library", 452 | "autoload": { 453 | "classmap": [ 454 | "src/" 455 | ] 456 | }, 457 | "notification-url": "https://packagist.org/downloads/", 458 | "license": [ 459 | "BSD-3-Clause" 460 | ], 461 | "authors": [ 462 | { 463 | "name": "Sebastian Bergmann", 464 | "email": "sebastian@phpunit.de", 465 | "role": "lead" 466 | } 467 | ], 468 | "description": "Simple template engine.", 469 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 470 | "keywords": [ 471 | "template" 472 | ], 473 | "time": "2015-06-21 13:50:34" 474 | }, 475 | { 476 | "name": "phpunit/php-timer", 477 | "version": "1.0.9", 478 | "source": { 479 | "type": "git", 480 | "url": "https://github.com/sebastianbergmann/php-timer.git", 481 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 482 | }, 483 | "dist": { 484 | "type": "zip", 485 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 486 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 487 | "shasum": "" 488 | }, 489 | "require": { 490 | "php": "^5.3.3 || ^7.0" 491 | }, 492 | "require-dev": { 493 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 494 | }, 495 | "type": "library", 496 | "extra": { 497 | "branch-alias": { 498 | "dev-master": "1.0-dev" 499 | } 500 | }, 501 | "autoload": { 502 | "classmap": [ 503 | "src/" 504 | ] 505 | }, 506 | "notification-url": "https://packagist.org/downloads/", 507 | "license": [ 508 | "BSD-3-Clause" 509 | ], 510 | "authors": [ 511 | { 512 | "name": "Sebastian Bergmann", 513 | "email": "sb@sebastian-bergmann.de", 514 | "role": "lead" 515 | } 516 | ], 517 | "description": "Utility class for timing", 518 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 519 | "keywords": [ 520 | "timer" 521 | ], 522 | "time": "2017-02-26 11:10:40" 523 | }, 524 | { 525 | "name": "phpunit/php-token-stream", 526 | "version": "2.0.2", 527 | "source": { 528 | "type": "git", 529 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 530 | "reference": "791198a2c6254db10131eecfe8c06670700904db" 531 | }, 532 | "dist": { 533 | "type": "zip", 534 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", 535 | "reference": "791198a2c6254db10131eecfe8c06670700904db", 536 | "shasum": "" 537 | }, 538 | "require": { 539 | "ext-tokenizer": "*", 540 | "php": "^7.0" 541 | }, 542 | "require-dev": { 543 | "phpunit/phpunit": "^6.2.4" 544 | }, 545 | "type": "library", 546 | "extra": { 547 | "branch-alias": { 548 | "dev-master": "2.0-dev" 549 | } 550 | }, 551 | "autoload": { 552 | "classmap": [ 553 | "src/" 554 | ] 555 | }, 556 | "notification-url": "https://packagist.org/downloads/", 557 | "license": [ 558 | "BSD-3-Clause" 559 | ], 560 | "authors": [ 561 | { 562 | "name": "Sebastian Bergmann", 563 | "email": "sebastian@phpunit.de" 564 | } 565 | ], 566 | "description": "Wrapper around PHP's tokenizer extension.", 567 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 568 | "keywords": [ 569 | "tokenizer" 570 | ], 571 | "time": "2017-11-27 05:48:46" 572 | }, 573 | { 574 | "name": "phpunit/phpunit", 575 | "version": "5.7.27", 576 | "source": { 577 | "type": "git", 578 | "url": "https://github.com/sebastianbergmann/phpunit.git", 579 | "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" 580 | }, 581 | "dist": { 582 | "type": "zip", 583 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", 584 | "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", 585 | "shasum": "" 586 | }, 587 | "require": { 588 | "ext-dom": "*", 589 | "ext-json": "*", 590 | "ext-libxml": "*", 591 | "ext-mbstring": "*", 592 | "ext-xml": "*", 593 | "myclabs/deep-copy": "~1.3", 594 | "php": "^5.6 || ^7.0", 595 | "phpspec/prophecy": "^1.6.2", 596 | "phpunit/php-code-coverage": "^4.0.4", 597 | "phpunit/php-file-iterator": "~1.4", 598 | "phpunit/php-text-template": "~1.2", 599 | "phpunit/php-timer": "^1.0.6", 600 | "phpunit/phpunit-mock-objects": "^3.2", 601 | "sebastian/comparator": "^1.2.4", 602 | "sebastian/diff": "^1.4.3", 603 | "sebastian/environment": "^1.3.4 || ^2.0", 604 | "sebastian/exporter": "~2.0", 605 | "sebastian/global-state": "^1.1", 606 | "sebastian/object-enumerator": "~2.0", 607 | "sebastian/resource-operations": "~1.0", 608 | "sebastian/version": "^1.0.6|^2.0.1", 609 | "symfony/yaml": "~2.1|~3.0|~4.0" 610 | }, 611 | "conflict": { 612 | "phpdocumentor/reflection-docblock": "3.0.2" 613 | }, 614 | "require-dev": { 615 | "ext-pdo": "*" 616 | }, 617 | "suggest": { 618 | "ext-xdebug": "*", 619 | "phpunit/php-invoker": "~1.1" 620 | }, 621 | "bin": [ 622 | "phpunit" 623 | ], 624 | "type": "library", 625 | "extra": { 626 | "branch-alias": { 627 | "dev-master": "5.7.x-dev" 628 | } 629 | }, 630 | "autoload": { 631 | "classmap": [ 632 | "src/" 633 | ] 634 | }, 635 | "notification-url": "https://packagist.org/downloads/", 636 | "license": [ 637 | "BSD-3-Clause" 638 | ], 639 | "authors": [ 640 | { 641 | "name": "Sebastian Bergmann", 642 | "email": "sebastian@phpunit.de", 643 | "role": "lead" 644 | } 645 | ], 646 | "description": "The PHP Unit Testing framework.", 647 | "homepage": "https://phpunit.de/", 648 | "keywords": [ 649 | "phpunit", 650 | "testing", 651 | "xunit" 652 | ], 653 | "time": "2018-02-01 05:50:59" 654 | }, 655 | { 656 | "name": "phpunit/phpunit-mock-objects", 657 | "version": "3.4.4", 658 | "source": { 659 | "type": "git", 660 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 661 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" 662 | }, 663 | "dist": { 664 | "type": "zip", 665 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", 666 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", 667 | "shasum": "" 668 | }, 669 | "require": { 670 | "doctrine/instantiator": "^1.0.2", 671 | "php": "^5.6 || ^7.0", 672 | "phpunit/php-text-template": "^1.2", 673 | "sebastian/exporter": "^1.2 || ^2.0" 674 | }, 675 | "conflict": { 676 | "phpunit/phpunit": "<5.4.0" 677 | }, 678 | "require-dev": { 679 | "phpunit/phpunit": "^5.4" 680 | }, 681 | "suggest": { 682 | "ext-soap": "*" 683 | }, 684 | "type": "library", 685 | "extra": { 686 | "branch-alias": { 687 | "dev-master": "3.2.x-dev" 688 | } 689 | }, 690 | "autoload": { 691 | "classmap": [ 692 | "src/" 693 | ] 694 | }, 695 | "notification-url": "https://packagist.org/downloads/", 696 | "license": [ 697 | "BSD-3-Clause" 698 | ], 699 | "authors": [ 700 | { 701 | "name": "Sebastian Bergmann", 702 | "email": "sb@sebastian-bergmann.de", 703 | "role": "lead" 704 | } 705 | ], 706 | "description": "Mock Object library for PHPUnit", 707 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 708 | "keywords": [ 709 | "mock", 710 | "xunit" 711 | ], 712 | "time": "2017-06-30 09:13:00" 713 | }, 714 | { 715 | "name": "sebastian/code-unit-reverse-lookup", 716 | "version": "1.0.1", 717 | "source": { 718 | "type": "git", 719 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 720 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" 721 | }, 722 | "dist": { 723 | "type": "zip", 724 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 725 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 726 | "shasum": "" 727 | }, 728 | "require": { 729 | "php": "^5.6 || ^7.0" 730 | }, 731 | "require-dev": { 732 | "phpunit/phpunit": "^5.7 || ^6.0" 733 | }, 734 | "type": "library", 735 | "extra": { 736 | "branch-alias": { 737 | "dev-master": "1.0.x-dev" 738 | } 739 | }, 740 | "autoload": { 741 | "classmap": [ 742 | "src/" 743 | ] 744 | }, 745 | "notification-url": "https://packagist.org/downloads/", 746 | "license": [ 747 | "BSD-3-Clause" 748 | ], 749 | "authors": [ 750 | { 751 | "name": "Sebastian Bergmann", 752 | "email": "sebastian@phpunit.de" 753 | } 754 | ], 755 | "description": "Looks up which function or method a line of code belongs to", 756 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 757 | "time": "2017-03-04 06:30:41" 758 | }, 759 | { 760 | "name": "sebastian/comparator", 761 | "version": "1.2.4", 762 | "source": { 763 | "type": "git", 764 | "url": "https://github.com/sebastianbergmann/comparator.git", 765 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 766 | }, 767 | "dist": { 768 | "type": "zip", 769 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 770 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 771 | "shasum": "" 772 | }, 773 | "require": { 774 | "php": ">=5.3.3", 775 | "sebastian/diff": "~1.2", 776 | "sebastian/exporter": "~1.2 || ~2.0" 777 | }, 778 | "require-dev": { 779 | "phpunit/phpunit": "~4.4" 780 | }, 781 | "type": "library", 782 | "extra": { 783 | "branch-alias": { 784 | "dev-master": "1.2.x-dev" 785 | } 786 | }, 787 | "autoload": { 788 | "classmap": [ 789 | "src/" 790 | ] 791 | }, 792 | "notification-url": "https://packagist.org/downloads/", 793 | "license": [ 794 | "BSD-3-Clause" 795 | ], 796 | "authors": [ 797 | { 798 | "name": "Jeff Welch", 799 | "email": "whatthejeff@gmail.com" 800 | }, 801 | { 802 | "name": "Volker Dusch", 803 | "email": "github@wallbash.com" 804 | }, 805 | { 806 | "name": "Bernhard Schussek", 807 | "email": "bschussek@2bepublished.at" 808 | }, 809 | { 810 | "name": "Sebastian Bergmann", 811 | "email": "sebastian@phpunit.de" 812 | } 813 | ], 814 | "description": "Provides the functionality to compare PHP values for equality", 815 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 816 | "keywords": [ 817 | "comparator", 818 | "compare", 819 | "equality" 820 | ], 821 | "time": "2017-01-29 09:50:25" 822 | }, 823 | { 824 | "name": "sebastian/diff", 825 | "version": "1.4.3", 826 | "source": { 827 | "type": "git", 828 | "url": "https://github.com/sebastianbergmann/diff.git", 829 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 830 | }, 831 | "dist": { 832 | "type": "zip", 833 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", 834 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 835 | "shasum": "" 836 | }, 837 | "require": { 838 | "php": "^5.3.3 || ^7.0" 839 | }, 840 | "require-dev": { 841 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 842 | }, 843 | "type": "library", 844 | "extra": { 845 | "branch-alias": { 846 | "dev-master": "1.4-dev" 847 | } 848 | }, 849 | "autoload": { 850 | "classmap": [ 851 | "src/" 852 | ] 853 | }, 854 | "notification-url": "https://packagist.org/downloads/", 855 | "license": [ 856 | "BSD-3-Clause" 857 | ], 858 | "authors": [ 859 | { 860 | "name": "Kore Nordmann", 861 | "email": "mail@kore-nordmann.de" 862 | }, 863 | { 864 | "name": "Sebastian Bergmann", 865 | "email": "sebastian@phpunit.de" 866 | } 867 | ], 868 | "description": "Diff implementation", 869 | "homepage": "https://github.com/sebastianbergmann/diff", 870 | "keywords": [ 871 | "diff" 872 | ], 873 | "time": "2017-05-22 07:24:03" 874 | }, 875 | { 876 | "name": "sebastian/environment", 877 | "version": "2.0.0", 878 | "source": { 879 | "type": "git", 880 | "url": "https://github.com/sebastianbergmann/environment.git", 881 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" 882 | }, 883 | "dist": { 884 | "type": "zip", 885 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 886 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 887 | "shasum": "" 888 | }, 889 | "require": { 890 | "php": "^5.6 || ^7.0" 891 | }, 892 | "require-dev": { 893 | "phpunit/phpunit": "^5.0" 894 | }, 895 | "type": "library", 896 | "extra": { 897 | "branch-alias": { 898 | "dev-master": "2.0.x-dev" 899 | } 900 | }, 901 | "autoload": { 902 | "classmap": [ 903 | "src/" 904 | ] 905 | }, 906 | "notification-url": "https://packagist.org/downloads/", 907 | "license": [ 908 | "BSD-3-Clause" 909 | ], 910 | "authors": [ 911 | { 912 | "name": "Sebastian Bergmann", 913 | "email": "sebastian@phpunit.de" 914 | } 915 | ], 916 | "description": "Provides functionality to handle HHVM/PHP environments", 917 | "homepage": "http://www.github.com/sebastianbergmann/environment", 918 | "keywords": [ 919 | "Xdebug", 920 | "environment", 921 | "hhvm" 922 | ], 923 | "time": "2016-11-26 07:53:53" 924 | }, 925 | { 926 | "name": "sebastian/exporter", 927 | "version": "2.0.0", 928 | "source": { 929 | "type": "git", 930 | "url": "https://github.com/sebastianbergmann/exporter.git", 931 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" 932 | }, 933 | "dist": { 934 | "type": "zip", 935 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 936 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 937 | "shasum": "" 938 | }, 939 | "require": { 940 | "php": ">=5.3.3", 941 | "sebastian/recursion-context": "~2.0" 942 | }, 943 | "require-dev": { 944 | "ext-mbstring": "*", 945 | "phpunit/phpunit": "~4.4" 946 | }, 947 | "type": "library", 948 | "extra": { 949 | "branch-alias": { 950 | "dev-master": "2.0.x-dev" 951 | } 952 | }, 953 | "autoload": { 954 | "classmap": [ 955 | "src/" 956 | ] 957 | }, 958 | "notification-url": "https://packagist.org/downloads/", 959 | "license": [ 960 | "BSD-3-Clause" 961 | ], 962 | "authors": [ 963 | { 964 | "name": "Jeff Welch", 965 | "email": "whatthejeff@gmail.com" 966 | }, 967 | { 968 | "name": "Volker Dusch", 969 | "email": "github@wallbash.com" 970 | }, 971 | { 972 | "name": "Bernhard Schussek", 973 | "email": "bschussek@2bepublished.at" 974 | }, 975 | { 976 | "name": "Sebastian Bergmann", 977 | "email": "sebastian@phpunit.de" 978 | }, 979 | { 980 | "name": "Adam Harvey", 981 | "email": "aharvey@php.net" 982 | } 983 | ], 984 | "description": "Provides the functionality to export PHP variables for visualization", 985 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 986 | "keywords": [ 987 | "export", 988 | "exporter" 989 | ], 990 | "time": "2016-11-19 08:54:04" 991 | }, 992 | { 993 | "name": "sebastian/global-state", 994 | "version": "1.1.1", 995 | "source": { 996 | "type": "git", 997 | "url": "https://github.com/sebastianbergmann/global-state.git", 998 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 999 | }, 1000 | "dist": { 1001 | "type": "zip", 1002 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1003 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1004 | "shasum": "" 1005 | }, 1006 | "require": { 1007 | "php": ">=5.3.3" 1008 | }, 1009 | "require-dev": { 1010 | "phpunit/phpunit": "~4.2" 1011 | }, 1012 | "suggest": { 1013 | "ext-uopz": "*" 1014 | }, 1015 | "type": "library", 1016 | "extra": { 1017 | "branch-alias": { 1018 | "dev-master": "1.0-dev" 1019 | } 1020 | }, 1021 | "autoload": { 1022 | "classmap": [ 1023 | "src/" 1024 | ] 1025 | }, 1026 | "notification-url": "https://packagist.org/downloads/", 1027 | "license": [ 1028 | "BSD-3-Clause" 1029 | ], 1030 | "authors": [ 1031 | { 1032 | "name": "Sebastian Bergmann", 1033 | "email": "sebastian@phpunit.de" 1034 | } 1035 | ], 1036 | "description": "Snapshotting of global state", 1037 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1038 | "keywords": [ 1039 | "global state" 1040 | ], 1041 | "time": "2015-10-12 03:26:01" 1042 | }, 1043 | { 1044 | "name": "sebastian/object-enumerator", 1045 | "version": "2.0.1", 1046 | "source": { 1047 | "type": "git", 1048 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1049 | "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" 1050 | }, 1051 | "dist": { 1052 | "type": "zip", 1053 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", 1054 | "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", 1055 | "shasum": "" 1056 | }, 1057 | "require": { 1058 | "php": ">=5.6", 1059 | "sebastian/recursion-context": "~2.0" 1060 | }, 1061 | "require-dev": { 1062 | "phpunit/phpunit": "~5" 1063 | }, 1064 | "type": "library", 1065 | "extra": { 1066 | "branch-alias": { 1067 | "dev-master": "2.0.x-dev" 1068 | } 1069 | }, 1070 | "autoload": { 1071 | "classmap": [ 1072 | "src/" 1073 | ] 1074 | }, 1075 | "notification-url": "https://packagist.org/downloads/", 1076 | "license": [ 1077 | "BSD-3-Clause" 1078 | ], 1079 | "authors": [ 1080 | { 1081 | "name": "Sebastian Bergmann", 1082 | "email": "sebastian@phpunit.de" 1083 | } 1084 | ], 1085 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1086 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1087 | "time": "2017-02-18 15:18:39" 1088 | }, 1089 | { 1090 | "name": "sebastian/recursion-context", 1091 | "version": "2.0.0", 1092 | "source": { 1093 | "type": "git", 1094 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1095 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" 1096 | }, 1097 | "dist": { 1098 | "type": "zip", 1099 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", 1100 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", 1101 | "shasum": "" 1102 | }, 1103 | "require": { 1104 | "php": ">=5.3.3" 1105 | }, 1106 | "require-dev": { 1107 | "phpunit/phpunit": "~4.4" 1108 | }, 1109 | "type": "library", 1110 | "extra": { 1111 | "branch-alias": { 1112 | "dev-master": "2.0.x-dev" 1113 | } 1114 | }, 1115 | "autoload": { 1116 | "classmap": [ 1117 | "src/" 1118 | ] 1119 | }, 1120 | "notification-url": "https://packagist.org/downloads/", 1121 | "license": [ 1122 | "BSD-3-Clause" 1123 | ], 1124 | "authors": [ 1125 | { 1126 | "name": "Jeff Welch", 1127 | "email": "whatthejeff@gmail.com" 1128 | }, 1129 | { 1130 | "name": "Sebastian Bergmann", 1131 | "email": "sebastian@phpunit.de" 1132 | }, 1133 | { 1134 | "name": "Adam Harvey", 1135 | "email": "aharvey@php.net" 1136 | } 1137 | ], 1138 | "description": "Provides functionality to recursively process PHP variables", 1139 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1140 | "time": "2016-11-19 07:33:16" 1141 | }, 1142 | { 1143 | "name": "sebastian/resource-operations", 1144 | "version": "1.0.0", 1145 | "source": { 1146 | "type": "git", 1147 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1148 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" 1149 | }, 1150 | "dist": { 1151 | "type": "zip", 1152 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1153 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1154 | "shasum": "" 1155 | }, 1156 | "require": { 1157 | "php": ">=5.6.0" 1158 | }, 1159 | "type": "library", 1160 | "extra": { 1161 | "branch-alias": { 1162 | "dev-master": "1.0.x-dev" 1163 | } 1164 | }, 1165 | "autoload": { 1166 | "classmap": [ 1167 | "src/" 1168 | ] 1169 | }, 1170 | "notification-url": "https://packagist.org/downloads/", 1171 | "license": [ 1172 | "BSD-3-Clause" 1173 | ], 1174 | "authors": [ 1175 | { 1176 | "name": "Sebastian Bergmann", 1177 | "email": "sebastian@phpunit.de" 1178 | } 1179 | ], 1180 | "description": "Provides a list of PHP built-in functions that operate on resources", 1181 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1182 | "time": "2015-07-28 20:34:47" 1183 | }, 1184 | { 1185 | "name": "sebastian/version", 1186 | "version": "2.0.1", 1187 | "source": { 1188 | "type": "git", 1189 | "url": "https://github.com/sebastianbergmann/version.git", 1190 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1191 | }, 1192 | "dist": { 1193 | "type": "zip", 1194 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1195 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1196 | "shasum": "" 1197 | }, 1198 | "require": { 1199 | "php": ">=5.6" 1200 | }, 1201 | "type": "library", 1202 | "extra": { 1203 | "branch-alias": { 1204 | "dev-master": "2.0.x-dev" 1205 | } 1206 | }, 1207 | "autoload": { 1208 | "classmap": [ 1209 | "src/" 1210 | ] 1211 | }, 1212 | "notification-url": "https://packagist.org/downloads/", 1213 | "license": [ 1214 | "BSD-3-Clause" 1215 | ], 1216 | "authors": [ 1217 | { 1218 | "name": "Sebastian Bergmann", 1219 | "email": "sebastian@phpunit.de", 1220 | "role": "lead" 1221 | } 1222 | ], 1223 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1224 | "homepage": "https://github.com/sebastianbergmann/version", 1225 | "time": "2016-10-03 07:35:21" 1226 | }, 1227 | { 1228 | "name": "symfony/yaml", 1229 | "version": "v4.0.8", 1230 | "source": { 1231 | "type": "git", 1232 | "url": "https://github.com/symfony/yaml.git", 1233 | "reference": "8b34ebb5989df61cbd77eff29a02c4db9ac1069c" 1234 | }, 1235 | "dist": { 1236 | "type": "zip", 1237 | "url": "https://api.github.com/repos/symfony/yaml/zipball/8b34ebb5989df61cbd77eff29a02c4db9ac1069c", 1238 | "reference": "8b34ebb5989df61cbd77eff29a02c4db9ac1069c", 1239 | "shasum": "" 1240 | }, 1241 | "require": { 1242 | "php": "^7.1.3" 1243 | }, 1244 | "conflict": { 1245 | "symfony/console": "<3.4" 1246 | }, 1247 | "require-dev": { 1248 | "symfony/console": "~3.4|~4.0" 1249 | }, 1250 | "suggest": { 1251 | "symfony/console": "For validating YAML files using the lint command" 1252 | }, 1253 | "type": "library", 1254 | "extra": { 1255 | "branch-alias": { 1256 | "dev-master": "4.0-dev" 1257 | } 1258 | }, 1259 | "autoload": { 1260 | "psr-4": { 1261 | "Symfony\\Component\\Yaml\\": "" 1262 | }, 1263 | "exclude-from-classmap": [ 1264 | "/Tests/" 1265 | ] 1266 | }, 1267 | "notification-url": "https://packagist.org/downloads/", 1268 | "license": [ 1269 | "MIT" 1270 | ], 1271 | "authors": [ 1272 | { 1273 | "name": "Fabien Potencier", 1274 | "email": "fabien@symfony.com" 1275 | }, 1276 | { 1277 | "name": "Symfony Community", 1278 | "homepage": "https://symfony.com/contributors" 1279 | } 1280 | ], 1281 | "description": "Symfony Yaml Component", 1282 | "homepage": "https://symfony.com", 1283 | "time": "2018-04-03 05:24:00" 1284 | }, 1285 | { 1286 | "name": "webmozart/assert", 1287 | "version": "1.3.0", 1288 | "source": { 1289 | "type": "git", 1290 | "url": "https://github.com/webmozart/assert.git", 1291 | "reference": "0df1908962e7a3071564e857d86874dad1ef204a" 1292 | }, 1293 | "dist": { 1294 | "type": "zip", 1295 | "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", 1296 | "reference": "0df1908962e7a3071564e857d86874dad1ef204a", 1297 | "shasum": "" 1298 | }, 1299 | "require": { 1300 | "php": "^5.3.3 || ^7.0" 1301 | }, 1302 | "require-dev": { 1303 | "phpunit/phpunit": "^4.6", 1304 | "sebastian/version": "^1.0.1" 1305 | }, 1306 | "type": "library", 1307 | "extra": { 1308 | "branch-alias": { 1309 | "dev-master": "1.3-dev" 1310 | } 1311 | }, 1312 | "autoload": { 1313 | "psr-4": { 1314 | "Webmozart\\Assert\\": "src/" 1315 | } 1316 | }, 1317 | "notification-url": "https://packagist.org/downloads/", 1318 | "license": [ 1319 | "MIT" 1320 | ], 1321 | "authors": [ 1322 | { 1323 | "name": "Bernhard Schussek", 1324 | "email": "bschussek@gmail.com" 1325 | } 1326 | ], 1327 | "description": "Assertions to validate method input/output with nice error messages.", 1328 | "keywords": [ 1329 | "assert", 1330 | "check", 1331 | "validate" 1332 | ], 1333 | "time": "2018-01-29 19:49:41" 1334 | } 1335 | ], 1336 | "packages-dev": [], 1337 | "aliases": [], 1338 | "minimum-stability": "stable", 1339 | "stability-flags": [], 1340 | "prefer-stable": false, 1341 | "prefer-lowest": false, 1342 | "platform": [], 1343 | "platform-dev": [] 1344 | } 1345 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | Behavioral 8 | Creational 9 | Structural 10 | 11 | 12 | -------------------------------------------------------------------------------- /~images/AbstractFactory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/AbstractFactory.png -------------------------------------------------------------------------------- /~images/Adapter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Adapter.png -------------------------------------------------------------------------------- /~images/B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/B.png -------------------------------------------------------------------------------- /~images/BCS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/BCS.png -------------------------------------------------------------------------------- /~images/Bridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Bridge.png -------------------------------------------------------------------------------- /~images/Builder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Builder.png -------------------------------------------------------------------------------- /~images/C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/C.png -------------------------------------------------------------------------------- /~images/ChainOfResponsibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ChainOfResponsibility.png -------------------------------------------------------------------------------- /~images/Command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Command.png -------------------------------------------------------------------------------- /~images/Composite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Composite.png -------------------------------------------------------------------------------- /~images/Decorator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Decorator.png -------------------------------------------------------------------------------- /~images/Facade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Facade.png -------------------------------------------------------------------------------- /~images/FactoryMethod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/FactoryMethod.png -------------------------------------------------------------------------------- /~images/Flyweight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Flyweight.png -------------------------------------------------------------------------------- /~images/Interpreter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Interpreter.png -------------------------------------------------------------------------------- /~images/Iterator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Iterator.png -------------------------------------------------------------------------------- /~images/Mediator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Mediator.png -------------------------------------------------------------------------------- /~images/Memento.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Memento.png -------------------------------------------------------------------------------- /~images/Observer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Observer.png -------------------------------------------------------------------------------- /~images/Prototype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Prototype.png -------------------------------------------------------------------------------- /~images/Proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Proxy.png -------------------------------------------------------------------------------- /~images/S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/S.png -------------------------------------------------------------------------------- /~images/Singleton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Singleton.png -------------------------------------------------------------------------------- /~images/State.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/State.png -------------------------------------------------------------------------------- /~images/Strategy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Strategy.png -------------------------------------------------------------------------------- /~images/TemplateMethod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/TemplateMethod.png -------------------------------------------------------------------------------- /~images/Visitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/Visitor.png -------------------------------------------------------------------------------- /~images/aggregation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/aggregation.png -------------------------------------------------------------------------------- /~images/composition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/composition.png -------------------------------------------------------------------------------- /~images/dependency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/dependency.png -------------------------------------------------------------------------------- /~images/generalization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/generalization.png -------------------------------------------------------------------------------- /~images/ru/AbstractFactory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/AbstractFactory.png -------------------------------------------------------------------------------- /~images/ru/Adapter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Adapter.png -------------------------------------------------------------------------------- /~images/ru/BCS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/BCS.png -------------------------------------------------------------------------------- /~images/ru/Bridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Bridge.png -------------------------------------------------------------------------------- /~images/ru/Builder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Builder.png -------------------------------------------------------------------------------- /~images/ru/ChainofResponsibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/ChainofResponsibility.png -------------------------------------------------------------------------------- /~images/ru/Command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Command.png -------------------------------------------------------------------------------- /~images/ru/Composite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Composite.png -------------------------------------------------------------------------------- /~images/ru/Decorator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Decorator.png -------------------------------------------------------------------------------- /~images/ru/Facade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Facade.png -------------------------------------------------------------------------------- /~images/ru/FactoryMethod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/FactoryMethod.png -------------------------------------------------------------------------------- /~images/ru/Flyweight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Flyweight.png -------------------------------------------------------------------------------- /~images/ru/Interpreter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Interpreter.png -------------------------------------------------------------------------------- /~images/ru/Iterator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Iterator.png -------------------------------------------------------------------------------- /~images/ru/Mediator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Mediator.png -------------------------------------------------------------------------------- /~images/ru/Memento.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Memento.png -------------------------------------------------------------------------------- /~images/ru/Observer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Observer.png -------------------------------------------------------------------------------- /~images/ru/Prototype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Prototype.png -------------------------------------------------------------------------------- /~images/ru/Proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Proxy.png -------------------------------------------------------------------------------- /~images/ru/Singleton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Singleton.png -------------------------------------------------------------------------------- /~images/ru/State.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/State.png -------------------------------------------------------------------------------- /~images/ru/Strategy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Strategy.png -------------------------------------------------------------------------------- /~images/ru/TemplateMethod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/TemplateMethod.png -------------------------------------------------------------------------------- /~images/ru/Visitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/legrch/php-design-patterns/61a5c1d72c3c10c0f1b96b46855f01d446fa0b1a/~images/ru/Visitor.png --------------------------------------------------------------------------------