├── .gitignore ├── .travis.yml ├── Behavioral ├── ChainOfResponsibilities │ ├── Handler.php │ ├── README.md │ ├── Request.php │ ├── Responsible │ │ ├── FastStorage.php │ │ └── SlowStorage.php │ ├── Tests │ │ └── ChainTest.php │ └── uml │ │ ├── ChainOfResponsibilities.uml │ │ ├── uml.png │ │ └── uml.svg ├── Command │ ├── CommandInterface.php │ ├── HelloCommand.php │ ├── Invoker.php │ ├── README.md │ ├── Receiver.php │ ├── Tests │ │ └── CommandTest.php │ └── uml │ │ ├── Command.uml │ │ ├── uml.png │ │ └── uml.svg ├── Iterator │ ├── Book.php │ ├── BookList.php │ ├── BookListIterator.php │ ├── BookListReverseIterator.php │ ├── README.md │ ├── Tests │ │ └── IteratorTest.php │ └── uml │ │ ├── Iterator.uml │ │ ├── uml.png │ │ └── uml.svg ├── Mediator │ ├── Colleague.php │ ├── Mediator.php │ ├── MediatorInterface.php │ ├── README.md │ ├── Subsystem │ │ ├── Client.php │ │ ├── Database.php │ │ └── Server.php │ ├── Tests │ │ └── MediatorTest.php │ └── uml │ │ ├── Mediator.uml │ │ ├── uml.png │ │ └── uml.svg ├── Memento │ ├── Caretaker.php │ ├── Memento.php │ ├── Originator.php │ ├── README.md │ ├── Tests │ │ └── MementoTest.php │ └── uml │ │ ├── Momento.uml │ │ ├── uml.png │ │ └── uml.svg ├── NullObject │ ├── LoggerInterface.php │ ├── NullLogger.php │ ├── PrintLogger.php │ ├── README.md │ ├── Service.php │ ├── Tests │ │ └── LoggerTest.php │ └── uml │ │ ├── NullObject.uml │ │ ├── uml.png │ │ └── uml.svg ├── Observer │ ├── README.md │ ├── Tests │ │ └── ObserverTest.php │ ├── User.php │ ├── UserObserver.php │ └── uml │ │ ├── Observer.uml │ │ ├── uml.png │ │ └── uml.svg ├── README.md ├── Specification │ ├── AbstractSpecification.php │ ├── Either.php │ ├── Item.php │ ├── Not.php │ ├── Plus.php │ ├── PriceSpecification.php │ ├── README.md │ ├── SpecificationInterface.php │ ├── Tests │ │ └── SpecificationTest.php │ └── uml │ │ ├── Specification.uml │ │ ├── uml.png │ │ └── uml.svg ├── State │ ├── CreateOrder.php │ ├── OrderController.php │ ├── OrderFactory.php │ ├── OrderInterface.php │ ├── README.md │ ├── ShippingOrder.php │ └── uml │ │ ├── State.uml │ │ ├── uml.png │ │ └── uml.svg ├── Strategy │ ├── ComparatorInterface.php │ ├── DateComparator.php │ ├── IdComparator.php │ ├── ObjectCollection.php │ ├── README.md │ ├── Tests │ │ └── StrategyTest.php │ └── uml │ │ ├── Strategy.uml │ │ ├── uml.png │ │ └── uml.svg ├── TemplateMethod │ ├── BeachJourney.php │ ├── CityJourney.php │ ├── Journey.php │ ├── README.md │ ├── Tests │ │ └── JourneyTest.php │ └── uml │ │ ├── TemplateMethod.uml │ │ ├── uml.png │ │ └── uml.svg └── Visitor │ ├── Group.php │ ├── README.md │ ├── Role.php │ ├── RolePrintVisitor.php │ ├── RoleVisitorInterface.php │ ├── Tests │ └── VisitorTest.php │ ├── User.php │ └── uml │ ├── Visitor.uml │ ├── uml.png │ └── uml.svg ├── Creational ├── AbstractFactory │ ├── AbstractFactory.php │ ├── Html │ │ ├── Picture.php │ │ └── Text.php │ ├── HtmlFactory.php │ ├── Json │ │ ├── Picture.php │ │ └── Text.php │ ├── JsonFactory.php │ ├── MediaInterface.php │ ├── Picture.php │ ├── README.md │ ├── Tests │ │ └── AbstractFactoryTest.php │ ├── Text.php │ └── uml │ │ ├── AbstractFactory.uml │ │ ├── uml.png │ │ └── uml.svg ├── Builder │ ├── BikeBuilder.php │ ├── BuilderInterface.php │ ├── CarBuilder.php │ ├── Director.php │ ├── Parts │ │ ├── Bike.php │ │ ├── Car.php │ │ ├── Door.php │ │ ├── Engine.php │ │ ├── README.md │ │ ├── Vehicle.php │ │ └── Wheel.php │ ├── README.md │ ├── Tests │ │ └── DirectorTest.php │ └── uml │ │ ├── Builder.uml │ │ ├── uml.png │ │ └── uml.svg ├── FactoryMethod │ ├── Bicycle.php │ ├── FactoryMethod.php │ ├── Ferrari.php │ ├── GermanFactory.php │ ├── ItalianFactory.php │ ├── Porsche.php │ ├── README.md │ ├── Tests │ │ └── FactoryMethodTest.php │ ├── VehicleInterface.php │ └── uml │ │ ├── FactoryMethod.uml │ │ ├── uml.png │ │ └── uml.svg ├── Multiton │ ├── Multiton.php │ ├── README.md │ └── uml │ │ ├── Multiton.uml │ │ ├── uml.png │ │ └── uml.svg ├── Pool │ ├── Pool.php │ ├── Processor.php │ ├── README.md │ ├── Tests │ │ └── PoolTest.php │ ├── Worker.php │ └── uml │ │ ├── Pool.uml │ │ ├── uml.png │ │ └── uml.svg ├── Prototype │ ├── BarBookPrototype.php │ ├── BookPrototype.php │ ├── FooBookPrototype.php │ ├── README.md │ ├── index.php │ └── uml │ │ ├── Prototype.uml │ │ ├── uml.png │ │ └── uml.svg ├── README.md ├── SimpleFactory │ ├── Bicycle.php │ ├── ConcreteFactory.php │ ├── README.md │ ├── Scooter.php │ ├── Tests │ │ └── SimpleFactoryTest.php │ ├── VehicleInterface.php │ └── uml │ │ ├── SimpleFactory.uml │ │ ├── uml.png │ │ └── uml.svg ├── Singleton │ ├── README.md │ ├── Singleton.php │ ├── Tests │ │ └── SingletonTest.php │ └── uml │ │ ├── Singleton.uml │ │ ├── uml.png │ │ └── uml.svg └── StaticFactory │ ├── FormatNumber.php │ ├── FormatString.php │ ├── FormatterInterface.php │ ├── README.md │ ├── StaticFactory.php │ ├── Tests │ └── StaticFactoryTest.php │ └── uml │ ├── StaticFactory.uml │ ├── uml.png │ └── uml.svg ├── LICENSE ├── More ├── Delegation │ ├── JuniorDeveloper.php │ ├── README.md │ ├── TeamLead.php │ ├── Tests │ │ └── DelegationTest.php │ ├── Usage.php │ └── uml │ │ ├── Delegation.uml │ │ ├── uml.png │ │ └── uml.svg ├── README.md ├── Repository │ ├── MemoryStorage.php │ ├── Post.php │ ├── PostRepository.php │ ├── README.md │ ├── Storage.php │ └── uml │ │ ├── Repository.uml │ │ ├── uml.png │ │ └── uml.svg └── ServiceLocator │ ├── DatabaseService.php │ ├── DatabaseServiceInterface.php │ ├── LogService.php │ ├── LogServiceInterface.php │ ├── README.md │ ├── ServiceLocator.php │ ├── ServiceLocatorInterface.php │ ├── Tests │ └── ServiceLocatorTest.php │ └── uml │ ├── ServiceLocator.uml │ ├── uml.png │ └── uml.svg ├── README.md ├── Structural ├── Adapter │ ├── Book.php │ ├── EBookAdapter.php │ ├── EBookInterface.php │ ├── Kindle.php │ ├── PaperBookInterface.php │ ├── README.md │ ├── Tests │ │ └── AdapterTest.php │ └── uml │ │ ├── Adapter.uml │ │ ├── uml.png │ │ └── uml.svg ├── Bridge │ ├── Assemble.php │ ├── Car.php │ ├── Motorcycle.php │ ├── Produce.php │ ├── README.md │ ├── Tests │ │ └── BridgeTest.php │ ├── Vehicle.php │ ├── Workshop.php │ └── uml │ │ ├── Bridge.uml │ │ ├── uml.png │ │ └── uml.svg ├── Composite │ ├── Form.php │ ├── FormElement.php │ ├── InputElement.php │ ├── README.md │ ├── Tests │ │ └── CompositeTest.php │ ├── TextElement.php │ └── uml │ │ ├── Composite.uml │ │ ├── uml.png │ │ ├── uml.svg │ │ └── uml.txt ├── DataMapper │ ├── README.md │ ├── Tests │ │ └── DataMapperTest.php │ ├── User.php │ ├── UserMapper.php │ └── uml │ │ ├── DataMapper.uml │ │ ├── uml.png │ │ └── uml.svg ├── Decorator │ ├── Decorator.php │ ├── README.md │ ├── RenderInJson.php │ ├── RenderInXml.php │ ├── RendererInterface.php │ ├── Tests │ │ └── DecoratorTest.php │ ├── Webservice.php │ └── uml │ │ ├── Decorator.uml │ │ ├── uml.png │ │ └── uml.svg ├── DependencyInjection │ ├── AbstractConfig.php │ ├── ArrayConfig.php │ ├── Connection.php │ ├── Parameters.php │ ├── README.md │ ├── Tests │ │ ├── DependencyInjectionTest.php │ │ └── config.php │ └── uml │ │ ├── DependencyInjection.uml │ │ ├── uml.png │ │ └── uml.svg ├── Facade │ ├── BiosInterface.php │ ├── Facade.php │ ├── OsInterface.php │ ├── README.md │ ├── Tests │ │ └── FacadeTest.php │ └── uml │ │ ├── Facade.uml │ │ ├── uml.png │ │ └── uml.svg ├── FluentInterface │ ├── README.md │ ├── Sql.php │ ├── Tests │ │ └── FluentInterfaceTest.php │ └── uml │ │ ├── FluentInterface.uml │ │ ├── uml.png │ │ └── uml.svg ├── Proxy │ ├── README.md │ ├── Record.php │ ├── RecordProxy.php │ └── uml │ │ ├── Proxy.uml │ │ ├── uml.png │ │ └── uml.svg ├── README.md └── Registry │ ├── README.md │ ├── Registry.php │ ├── Tests │ └── RegistryTest.php │ └── uml │ ├── Registry.uml │ ├── uml.png │ └── uml.svg ├── composer.json ├── composer.lock ├── composer.phar └── phpunit.xml.dist /.gitignore: -------------------------------------------------------------------------------- 1 | # common 2 | .idea 3 | /nbproject 4 | /vendor/ 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.3 4 | - 5.4 5 | - 5.5 6 | - hhvm 7 | 8 | before_script: 9 | - composer self-update 10 | - composer install --prefer-source --no-interaction --dev 11 | 12 | branches: 13 | only: 14 | - master 15 | 16 | matrix: 17 | allow_failures: 18 | - php: hhvm 19 | fast_finish: true 20 | -------------------------------------------------------------------------------- /Behavioral/ChainOfResponsibilities/README.md: -------------------------------------------------------------------------------- 1 | # Chain Of Responsibilities 2 | 3 | ## Propósito 4 | 5 | Construir uma cadeia de objetos para lidar com chamadas em ordem sequencial. Se 6 | um objeto não pode lidar com uma chamada, delega essa chamada para o próximo na 7 | cadeira (chain) e assim por diante. 8 | 9 | ## Exemplos 10 | 11 | * Framework de log, onde cada elemento da cadeia decide autonomamente o que fazer 12 | com uma mensagem de log 13 | * Filtro de Spam 14 | * Caching: primeiro objeto é uma instância de, por exemplo, uma interface 15 | Memcached; se ela não souber lidar com a requisição, passa para uma interface de 16 | banco de dados 17 | * Yii Framework: CFilterChain é uma cadeia de filtros de ação de controller. O 18 | ponto de execução é passado de um filtro para o próximo na cadeia e, apenas se 19 | todos os filtros disserem "sim", a ação pode ser invocada. 20 | 21 | ## Diagrama UML 22 | 23 | ![Alt ChainOfResponsibility UML Diagram](uml/uml.png) 24 | -------------------------------------------------------------------------------- /Behavioral/ChainOfResponsibilities/Request.php: -------------------------------------------------------------------------------- 1 | data = $data; 24 | } 25 | 26 | protected function processing(Request $req) 27 | { 28 | if ('get' === $req->verb) { 29 | if (array_key_exists($req->key, $this->data)) { 30 | // the handler IS responsible and then processes the request 31 | $req->response = $this->data[$req->key]; 32 | // instead of returning true, I could return the value but it proves 33 | // to be a bad idea. What if the value IS "false" ? 34 | return true; 35 | } 36 | } 37 | 38 | return false; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Behavioral/ChainOfResponsibilities/Responsible/SlowStorage.php: -------------------------------------------------------------------------------- 1 | data = $data; 31 | } 32 | 33 | protected function processing(Request $req) 34 | { 35 | if ('get' === $req->verb) { 36 | if (array_key_exists($req->key, $this->data)) { 37 | $req->response = $this->data[$req->key]; 38 | 39 | return true; 40 | } 41 | } 42 | 43 | return false; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Behavioral/ChainOfResponsibilities/uml/ChainOfResponsibilities.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\ChainOfResponsibilities\Handler 5 | 6 | \DesignPatterns\Behavioral\ChainOfResponsibilities\Handler 7 | \DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage 8 | \DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\FastStorage 9 | \DesignPatterns\Behavioral\ChainOfResponsibilities\Request 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Fields 30 | Constants 31 | Constructors 32 | Methods 33 | 34 | private 35 | 36 | 37 | -------------------------------------------------------------------------------- /Behavioral/ChainOfResponsibilities/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/ChainOfResponsibilities/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/Command/CommandInterface.php: -------------------------------------------------------------------------------- 1 | output = $console; 25 | } 26 | 27 | /** 28 | * execute and output "Hello World" 29 | */ 30 | public function execute() 31 | { 32 | // sometimes, there is no receiver and this is the command which 33 | // does all the work 34 | $this->output->write('Hello World'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Behavioral/Command/Invoker.php: -------------------------------------------------------------------------------- 1 | command = $cmd; 25 | } 26 | 27 | /** 28 | * executes the command 29 | */ 30 | public function run() 31 | { 32 | // here is a key feature of the invoker 33 | // the invoker is the same whatever is the command 34 | $this->command->execute(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Behavioral/Command/README.md: -------------------------------------------------------------------------------- 1 | # Command 2 | 3 | ## Propósito 4 | 5 | Encapsular invocação e desacoplação 6 | 7 | Tem-se um Invoker (invocador) e um Receiver (receptor). Esse Padrão usa um 8 | comando ("Command") para delegar a chamada ao método contra o Receiver e 9 | apresentar o mesmo método "execute". Assim, o Invoker sabe que é preciso chamar 10 | "execute" para processar o comando do cliente. O Receiver é desacoplado do 11 | Invoker. 12 | 13 | O segundo aspecto desse padrão é o `undo()`, que desfaz o método `execute()`. 14 | Command também pode ser agregado para combinar comandos mais complexos com um 15 | copiar-colar mínimo e confiando na composição em detrimento de herança. 16 | 17 | ## Exemplos 18 | 19 | * Um editor de texto: todos eventos são Commands que podem ser desfeitos, 20 | empilhados e salvos 21 | * Symfony2: Commands SF2 que podem ser rodados a partir da linha de comando (CLI) 22 | com apenas o Padrão Command em mente 23 | * Grandes ferramentas CLI usam subcomandos para distribuir várias tarefas e 24 | agrupá-las em "módulos", cada um podendo ser implementado com Command (por 25 | exemplo, Vagrant) 26 | 27 | ## Diagrama UML 28 | 29 | ![Alt Command UML Diagram](uml/uml.png) 30 | -------------------------------------------------------------------------------- /Behavioral/Command/Receiver.php: -------------------------------------------------------------------------------- 1 | invoker = new Invoker(); 28 | $this->receiver = new Receiver(); 29 | } 30 | 31 | public function testInvocation() 32 | { 33 | $this->invoker->setCommand(new HelloCommand($this->receiver)); 34 | $this->expectOutputString('Hello World'); 35 | $this->invoker->run(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Behavioral/Command/uml/Command.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\Command\HelloCommand 5 | 6 | \DesignPatterns\Behavioral\Command\Invoker 7 | \DesignPatterns\Behavioral\Command\HelloCommand 8 | \DesignPatterns\Behavioral\Command\Receiver 9 | \DesignPatterns\Behavioral\Command\CommandInterface 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Fields 22 | Constants 23 | Constructors 24 | Methods 25 | 26 | private 27 | 28 | 29 | -------------------------------------------------------------------------------- /Behavioral/Command/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/Command/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/Iterator/Book.php: -------------------------------------------------------------------------------- 1 | author = $author; 15 | $this->title = $title; 16 | } 17 | 18 | public function getAuthor() 19 | { 20 | return $this->author; 21 | } 22 | 23 | public function getTitle() 24 | { 25 | return $this->title; 26 | } 27 | 28 | public function getAuthorAndTitle() 29 | { 30 | return $this->getTitle() . ' by ' . $this->getAuthor(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Behavioral/Iterator/BookList.php: -------------------------------------------------------------------------------- 1 | count()) { 13 | return $this->books[$bookNumberToGet]; 14 | } 15 | 16 | return null; 17 | } 18 | 19 | public function addBook(Book $book) 20 | { 21 | $this->books[] = $book; 22 | 23 | return $this->count(); 24 | } 25 | 26 | public function removeBook(Book $bookToRemove) 27 | { 28 | foreach ($this as $key => $book) { 29 | /** @var Book $book */ 30 | if ($book->getAuthorAndTitle() === $bookToRemove->getAuthorAndTitle()) { 31 | unset($this->books[$key]); 32 | } 33 | } 34 | 35 | return $this->count(); 36 | } 37 | 38 | public function count() 39 | { 40 | return count($this->books); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Behavioral/Iterator/BookListReverseIterator.php: -------------------------------------------------------------------------------- 1 | bookList = $bookList; 11 | $this->currentBook = $this->bookList->count() - 1; 12 | } 13 | 14 | public function next() 15 | { 16 | $this->currentBook--; 17 | } 18 | 19 | public function valid() 20 | { 21 | return 0 <= $this->currentBook; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Behavioral/Iterator/README.md: -------------------------------------------------------------------------------- 1 | # Iterator 2 | 3 | ## Propósito 4 | 5 | Fazer um objeto "interagível" e fazê-lo parecer como uma coleção de objetos. 6 | 7 | ## Exemplos 8 | 9 | * Processar um arquivo linha a linha passando por todas as linhas (que têm uma 10 | representação de objeto) por um arquivo (que, claro, é um objeto, também) 11 | 12 | ## Nota 13 | 14 | Standard PHP Library (SPL) define uma interface Iterator que é adequada para isso! 15 | Frequentemente você vai querer implementar a interface Countable, também, para 16 | permitir `count($object)` em seu objeto iterável. 17 | 18 | ## Diagrama UML 19 | 20 | ![Alt Iterator UML Diagram](uml/uml.png) 21 | -------------------------------------------------------------------------------- /Behavioral/Iterator/uml/Iterator.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\Iterator\Book 5 | 6 | \DesignPatterns\Behavioral\Iterator\BookListReverseIterator 7 | \DesignPatterns\Behavioral\Iterator\BookList 8 | \DesignPatterns\Behavioral\Iterator\BookListIterator 9 | \DesignPatterns\Behavioral\Iterator\Book 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Fields 22 | Constants 23 | Constructors 24 | Methods 25 | 26 | private 27 | 28 | 29 | -------------------------------------------------------------------------------- /Behavioral/Iterator/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/Iterator/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/Mediator/Colleague.php: -------------------------------------------------------------------------------- 1 | mediator; 22 | } 23 | 24 | /** 25 | * @param MediatorInterface $medium 26 | */ 27 | public function __construct(MediatorInterface $medium) 28 | { 29 | // in this way, we are sure the concrete colleague knows the mediator 30 | $this->mediator = $medium; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Behavioral/Mediator/Mediator.php: -------------------------------------------------------------------------------- 1 | database = $db; 37 | $this->server = $srv; 38 | $this->client = $cl; 39 | } 40 | 41 | /** 42 | * make request 43 | */ 44 | public function makeRequest() 45 | { 46 | $this->server->process(); 47 | } 48 | 49 | /** 50 | * query db 51 | * @return mixed 52 | */ 53 | public function queryDb() 54 | { 55 | return $this->database->getData(); 56 | } 57 | 58 | /** 59 | * send response 60 | * 61 | * @param string $content 62 | */ 63 | public function sendResponse($content) 64 | { 65 | $this->client->output($content); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Behavioral/Mediator/MediatorInterface.php: -------------------------------------------------------------------------------- 1 | getMediator()->makeRequest(); 18 | } 19 | 20 | /** 21 | * output content 22 | * 23 | * @param string $content 24 | */ 25 | public function output($content) 26 | { 27 | echo $content; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Behavioral/Mediator/Subsystem/Database.php: -------------------------------------------------------------------------------- 1 | getMediator()->queryDb(); 18 | $this->getMediator()->sendResponse("Hello $data"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Behavioral/Mediator/Tests/MediatorTest.php: -------------------------------------------------------------------------------- 1 | client = new Client($media); 22 | $media->setColleague(new Database($media), $this->client, new Server($media)); 23 | } 24 | 25 | public function testOutputHelloWorld() 26 | { 27 | // testing if Hello World is output : 28 | $this->expectOutputString('Hello World'); 29 | // as you see, the 3 components Client, Server and Database are totally decoupled 30 | $this->client->request(); 31 | // Anyway, it remains complexity in the Mediator that's why the pattern 32 | // Observer is preferable in mnay situations. 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Behavioral/Mediator/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/Mediator/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/Memento/Caretaker.php: -------------------------------------------------------------------------------- 1 | setState("State1"); 17 | //Setting state to State2 18 | $originator->setState("State2"); 19 | //Saving State2 to Memento 20 | $savedStates[] = $originator->saveToMemento(); 21 | //Setting state to State3 22 | $originator->setState("State3"); 23 | 24 | // We can request multiple mementos, and choose which one to roll back to. 25 | // Saving State3 to Memento 26 | $savedStates[] = $originator->saveToMemento(); 27 | //Setting state to State4 28 | $originator->setState("State4"); 29 | 30 | $originator->restoreFromMemento($savedStates[1]); 31 | //State after restoring from Memento: State3 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Behavioral/Memento/Memento.php: -------------------------------------------------------------------------------- 1 | state = $stateToSave; 16 | } 17 | 18 | /** 19 | * @return mixed 20 | */ 21 | public function getState() 22 | { 23 | return $this->state; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Behavioral/Memento/Originator.php: -------------------------------------------------------------------------------- 1 | state = $state; 19 | } 20 | 21 | /** 22 | * @return Memento 23 | */ 24 | public function saveToMemento() 25 | { 26 | $state = is_object($this->state) ? clone $this->state : $this->state; 27 | 28 | return new Memento($state); 29 | } 30 | 31 | public function restoreFromMemento(Memento $memento) 32 | { 33 | $this->state = $memento->getState(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Behavioral/Memento/README.md: -------------------------------------------------------------------------------- 1 | # Memento 2 | 3 | ## Propósito 4 | 5 | Prover a habilidade de restaurar um objeto a seu estado anterior ("desfazer" 6 | através de rollback). 7 | 8 | O Padrão Memento é implementado com 3 objetos: Originator (originador), Caretaker 9 | (zelador) e Memento (memória). 10 | 11 | O Originator é algum objeto que tem um estado interno. 12 | 13 | Caretaker vai fazer alguma coisa para o Originator, mas espera ser apto para 14 | desfazer (undo) a mudança. O Caretaker primeiro pergunta ao Originator pelo 15 | objeto Memento. Então ele faz qualquer operação (ou sequência de operações) que 16 | foi designado. Para reverter (roll back) ao estado anterior às operações, ele 17 | retorna o objeto Memento ao Originator. O objeto Memento, em si, é opaco -- um 18 | que o Caretaker não pode (ou não deveria) mudar. 19 | 20 | Ao usar este Padrão, deve-se tomar cuidado se o Originator puder alterar outros 21 | objetos ou recuros -- Memento opera em um objeto único. 22 | 23 | ## Exemplos 24 | 25 | * A semente (seed) de um pseudo-gerador de números 26 | * O estado numa máquina de estados finitos 27 | 28 | ## Diagrama UML 29 | 30 | ![Alt Momento UML Diagram](uml/uml.png) 31 | -------------------------------------------------------------------------------- /Behavioral/Memento/uml/Momento.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\Memento\Caretaker 5 | 6 | \DesignPatterns\Behavioral\Memento\Caretaker 7 | \DesignPatterns\Behavioral\Memento\Originator 8 | \DesignPatterns\Behavioral\Memento\Memento 9 | 10 | 11 | 12 | 13 | 14 | 15 | Fields 16 | Constants 17 | Constructors 18 | Methods 19 | 20 | private 21 | 22 | 23 | -------------------------------------------------------------------------------- /Behavioral/Memento/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/Memento/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/NullObject/LoggerInterface.php: -------------------------------------------------------------------------------- 1 | menos casos de uso 12 | 13 | Toda vez que se tem um método que retorna um objeto ou `null`, você deveria 14 | retornar um objeto ou um `NullObject`. Com NullObject, você não precisa mais de 15 | uma declaração como `if (!is_null($obj)) { $obj->callSomething(); }`. 16 | 17 | ## Exemplos 18 | 19 | * Symfony2: null logger do profiler 20 | * Symfony2: null output em Symfony/Console 21 | * null handler num Padrão Chain of Responsibilities 22 | * null command num Padrão Command 23 | 24 | ## Diagrama UML 25 | 26 | ![Alt NullObject UML Diagram](uml/uml.png) 27 | -------------------------------------------------------------------------------- /Behavioral/NullObject/Service.php: -------------------------------------------------------------------------------- 1 | logger = $log; 23 | } 24 | 25 | /** 26 | * do something ... 27 | */ 28 | public function doSomething() 29 | { 30 | // no more check "if (!is_null($this->logger))..." with the NullObject pattern 31 | $this->logger->log('We are in ' . __METHOD__); 32 | // something to do... 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Behavioral/NullObject/Tests/LoggerTest.php: -------------------------------------------------------------------------------- 1 | expectOutputString(null); // no output 21 | $service->doSomething(); 22 | } 23 | 24 | public function testStandardLogger() 25 | { 26 | $service = new Service(new PrintLogger()); 27 | $this->expectOutputString('We are in DesignPatterns\Behavioral\NullObject\Service::doSomething'); 28 | $service->doSomething(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Behavioral/NullObject/uml/NullObject.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\NullObject\Service 5 | 6 | \DesignPatterns\Behavioral\NullObject\NullLogger 7 | \DesignPatterns\Behavioral\NullObject\PrintLogger 8 | \DesignPatterns\Behavioral\NullObject\LoggerInterface 9 | \DesignPatterns\Behavioral\NullObject\Service 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Fields 30 | Constants 31 | Constructors 32 | Methods 33 | 34 | private 35 | 36 | 37 | -------------------------------------------------------------------------------- /Behavioral/NullObject/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/NullObject/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/Observer/README.md: -------------------------------------------------------------------------------- 1 | # Observer 2 | 3 | ## Propósito 4 | 5 | Implementar um comportamento publicar/subscrever a um objeto. Sempre que um 6 | objeto "Subject" ("Assunto") muda seu estado, os "Observers" ("Observadores") 7 | anexos serão notificados. Isso é usado para diminuir a quantidade de objetos 8 | acoplados e proporcionar baixo acoplamento 9 | 10 | ## Exemplos 11 | 12 | * Um sistema de fila de mensagem é "observado" para mostrar o progresso de um 13 | job em uma GUI 14 | 15 | ## Nota 16 | 17 | PHP já define 2 interfaces que podem ajudar a implementar esse padrão: SplObserver and SplSubject. 18 | 19 | ## Diagrama UML 20 | 21 | ![Alt Observer UML Diagram](uml/uml.png) 22 | -------------------------------------------------------------------------------- /Behavioral/Observer/Tests/ObserverTest.php: -------------------------------------------------------------------------------- 1 | observer = new UserObserver(); 19 | } 20 | 21 | /** 22 | * Tests the notification 23 | */ 24 | public function testNotify() 25 | { 26 | $this->expectOutputString('DesignPatterns\Behavioral\Observer\User has been updated'); 27 | $subject = new User(); 28 | 29 | $subject->attach($this->observer); 30 | $subject->property = 123; 31 | } 32 | 33 | /** 34 | * Tests the subscribing 35 | */ 36 | public function testAttachDetach() 37 | { 38 | $subject = new User(); 39 | $this->assertAttributeEmpty('observers', $subject); 40 | $subject->attach($this->observer); 41 | $this->assertAttributeNotEmpty('observers', $subject); 42 | $subject->detach($this->observer); 43 | $this->assertAttributeEmpty('observers', $subject); 44 | } 45 | 46 | /** 47 | * Tests the update() invocation on a mockup 48 | */ 49 | public function testUpdateCalling() 50 | { 51 | $subject = new User(); 52 | $observer = $this->getMock('SplObserver'); 53 | $subject->attach($observer); 54 | 55 | $observer->expects($this->once()) 56 | ->method('update') 57 | ->with($subject); 58 | 59 | $subject->notify(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Behavioral/Observer/User.php: -------------------------------------------------------------------------------- 1 | observers[] = $observer; 37 | } 38 | 39 | /** 40 | * detach an observer 41 | * 42 | * @param \SplObserver $observer 43 | * 44 | * @return void 45 | */ 46 | public function detach(\SplObserver $observer) 47 | { 48 | $index = array_search($observer, $this->observers); 49 | 50 | if (false !== $index) { 51 | unset($this->observers[$index]); 52 | } 53 | } 54 | 55 | /** 56 | * notify observers 57 | * 58 | * @return void 59 | */ 60 | public function notify() 61 | { 62 | /** @var \SplObserver $observer */ 63 | foreach ($this->observers as $observer) { 64 | $observer->update($this); 65 | } 66 | } 67 | 68 | /** 69 | * Ideally one would better write setter/getter for all valid attributes and only call notify() 70 | * on attributes that matter when changed 71 | * 72 | * @param string $name 73 | * @param mixed $value 74 | * 75 | * @return void 76 | */ 77 | public function __set($name, $value) 78 | { 79 | $this->data[$name] = $value; 80 | 81 | // notify the observers, that user has been updated 82 | $this->notify(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Behavioral/Observer/UserObserver.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\Observer\User 5 | 6 | \DesignPatterns\Behavioral\Observer\UserObserver 7 | \DesignPatterns\Behavioral\Observer\User 8 | \SplSubject 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Fields 21 | Constants 22 | Constructors 23 | Methods 24 | 25 | private 26 | 27 | 28 | -------------------------------------------------------------------------------- /Behavioral/Observer/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/Observer/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/README.md: -------------------------------------------------------------------------------- 1 | # Comportamental 2 | 3 | Em Engenharia de Software, Padrão de Projeto Comportamentais identificam padrões 4 | de comunicação comuns entre objetos. Ao fazer isso, esses Padrões aumentam a 5 | flexibilidade na realização dessa comunicação. 6 | 7 | * [ChainOfResponsibilities](ChainOfResponsibilities) [:notebook:](http://pt.wikipedia.org/wiki/Chain_of_Responsibility) 8 | * [Command](Command) [:notebook:](http://pt.wikipedia.org/wiki/Command) 9 | * [Iterator](Iterator) [:notebook:](http://pt.wikipedia.org/wiki/Iterator) 10 | * [Mediator](Mediator) [:notebook:](http://pt.wikipedia.org/wiki/Mediator) 11 | * [Memento](Memento) [:notebook:](http://pt.wikipedia.org/wiki/Memento_(inform%C3%A1tica)) 12 | * [NullObject](NullObject) [:notebook:](http://en.wikipedia.org/wiki/Null_Object_pattern) 13 | * [Observer](Observer) [:notebook:](http://pt.wikipedia.org/wiki/Observer) 14 | * [Specification](Specification) [:notebook:](http://en.wikipedia.org/wiki/Specification_pattern) 15 | * [State](State) [:notebook:](http://pt.wikipedia.org/wiki/State) 16 | * [Strategy](Strategy) [:notebook:](http://pt.wikipedia.org/wiki/Strategy) 17 | * [TemplateMethod](TemplateMethod) [:notebook:](http://pt.wikipedia.org/wiki/Template_Method) 18 | * [Visitor](Visitor) [:notebook:](http://pt.wikipedia.org/wiki/Visitor_pattern) 19 | -------------------------------------------------------------------------------- /Behavioral/Specification/AbstractSpecification.php: -------------------------------------------------------------------------------- 1 | left = $left; 22 | $this->right = $right; 23 | } 24 | 25 | /** 26 | * Returns the evaluation of both wrapped specifications as a logical OR 27 | * 28 | * @param Item $item 29 | * 30 | * @return bool 31 | */ 32 | public function isSatisfiedBy(Item $item) 33 | { 34 | return $this->left->isSatisfiedBy($item) || $this->right->isSatisfiedBy($item); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Behavioral/Specification/Item.php: -------------------------------------------------------------------------------- 1 | price = $price; 19 | } 20 | 21 | /** 22 | * Get the items price 23 | * 24 | * @return int 25 | */ 26 | public function getPrice() 27 | { 28 | return $this->price; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Behavioral/Specification/Not.php: -------------------------------------------------------------------------------- 1 | spec = $spec; 20 | } 21 | 22 | /** 23 | * Returns the negated result of the wrapped specification 24 | * 25 | * @param Item $item 26 | * 27 | * @return bool 28 | */ 29 | public function isSatisfiedBy(Item $item) 30 | { 31 | return !$this->spec->isSatisfiedBy($item); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Behavioral/Specification/Plus.php: -------------------------------------------------------------------------------- 1 | left = $left; 22 | $this->right = $right; 23 | } 24 | 25 | /** 26 | * Checks if the composite AND of specifications passes 27 | * 28 | * @param Item $item 29 | * 30 | * @return bool 31 | */ 32 | public function isSatisfiedBy(Item $item) 33 | { 34 | return $this->left->isSatisfiedBy($item) && $this->right->isSatisfiedBy($item); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Behavioral/Specification/PriceSpecification.php: -------------------------------------------------------------------------------- 1 | maxPrice = $maxPrice; 20 | } 21 | 22 | /** 23 | * Sets the optional minimum price 24 | * 25 | * @param int $minPrice 26 | */ 27 | public function setMinPrice($minPrice) 28 | { 29 | $this->minPrice = $minPrice; 30 | } 31 | 32 | /** 33 | * Checks if Item price falls between bounds 34 | * 35 | * @param Item $item 36 | * 37 | * @return bool 38 | */ 39 | public function isSatisfiedBy(Item $item) 40 | { 41 | if (!empty($this->maxPrice) && $item->getPrice() > $this->maxPrice) { 42 | return false; 43 | } 44 | if (!empty($this->minPrice) && $item->getPrice() < $this->minPrice) { 45 | return false; 46 | } 47 | 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Behavioral/Specification/README.md: -------------------------------------------------------------------------------- 1 | # Specification 2 | 3 | ## Propósito 4 | 5 | Construir uma especificação clara de regras de negócio, na qual objetos podem ser 6 | verificados. A classe de especificação tem um método chamado `isSatisfiedBy` que 7 | retorna `true` ou `false`, dependendo se dado objeto satisfaz a especificação. 8 | 9 | ## Diagrama UML 10 | 11 | ![Alt Specification UML Diagram](uml/uml.png) 12 | -------------------------------------------------------------------------------- /Behavioral/Specification/SpecificationInterface.php: -------------------------------------------------------------------------------- 1 | order = $order; 26 | } 27 | 28 | /** 29 | * @return mixed 30 | */ 31 | public function shipOrder() 32 | { 33 | $this->order['status'] = 'shipping'; 34 | $this->order['updatedTime'] = time(); 35 | 36 | // Setting the new order status into database; 37 | return $this->updateOrder($this->order); 38 | } 39 | 40 | /** 41 | * @return mixed|void 42 | * @throws \Exception 43 | */ 44 | public function completeOrder() 45 | { 46 | //Can not complete the order which status is created, throw exception; 47 | throw new \Exception('Can not complete the order which status is created!'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Behavioral/State/OrderController.php: -------------------------------------------------------------------------------- 1 | shipOrder(); 18 | } catch (Exception $e) { 19 | //handle error! 20 | } 21 | // response to browser 22 | } 23 | 24 | /** 25 | * @param int $id 26 | */ 27 | public function completeAction($id) 28 | { 29 | $order = OrderFactory::getOrder($id); 30 | try { 31 | $order->completeOrder(); 32 | } catch (Exception $e) { 33 | //handle error! 34 | } 35 | // response to browser 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Behavioral/State/OrderFactory.php: -------------------------------------------------------------------------------- 1 | order = $order; 26 | } 27 | 28 | /** 29 | * @return mixed|void 30 | * @throws \Exception 31 | */ 32 | public function shipOrder() 33 | { 34 | //Can not ship the order which status is shipping, throw exception; 35 | throw new \Exception('Can not ship the order which status is shipping!'); 36 | } 37 | 38 | /** 39 | * @return mixed 40 | */ 41 | public function completeOrder() 42 | { 43 | $this->order['status'] = 'completed'; 44 | $this->order['updatedTime'] = time(); 45 | 46 | // Setting the new order status into database; 47 | return $this->updateOrder($order); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Behavioral/State/uml/State.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\State\OrderInterface 5 | 6 | \DesignPatterns\Behavioral\State\OrderFactory 7 | \DesignPatterns\Behavioral\State\CreateOrder 8 | \DesignPatterns\Behavioral\State\OrderController 9 | \DesignPatterns\Behavioral\State\OrderInterface 10 | \DesignPatterns\Behavioral\State\ShippingOrder 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | Fields 31 | Constants 32 | Constructors 33 | Methods 34 | 35 | private 36 | 37 | 38 | -------------------------------------------------------------------------------- /Behavioral/State/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/State/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/Strategy/ComparatorInterface.php: -------------------------------------------------------------------------------- 1 | elements = $elements; 26 | } 27 | 28 | /** 29 | * @return array 30 | */ 31 | public function sort() 32 | { 33 | if (!$this->comparator) { 34 | throw new \LogicException("Comparator is not set"); 35 | } 36 | 37 | $callback = array($this->comparator, 'compare'); 38 | uasort($this->elements, $callback); 39 | 40 | return $this->elements; 41 | } 42 | 43 | /** 44 | * @param ComparatorInterface $comparator 45 | * 46 | * @return void 47 | */ 48 | public function setComparator(ComparatorInterface $comparator) 49 | { 50 | $this->comparator = $comparator; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Behavioral/Strategy/README.md: -------------------------------------------------------------------------------- 1 | # Strategy 2 | 3 | ## Terminologia 4 | 5 | * Context (Contexto) 6 | * Strategy (Estratégia) 7 | * Concrete Strategy (Estratégia Concreta) 8 | 9 | ## Propósito 10 | 11 | Separar estratégias e permitir uma troca rápida entre elas. Esse padrão também 12 | é uma boa alternativa a herança -- não é preciso ter uma classe abstrata que é 13 | estendida. 14 | 15 | ## Exemplos 16 | 17 | * Ordenar uma lista de objetos, uma estratégia por data, outra por ID 18 | * Simplificar teste unitário: alternar entre armazenado em arquivo e em memória 19 | 20 | ## Diagrama UML 21 | 22 | ![Alt Strategy UML Diagram](uml/uml.png) 23 | -------------------------------------------------------------------------------- /Behavioral/Strategy/uml/Strategy.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\Strategy\ComparatorInterface 5 | 6 | \DesignPatterns\Behavioral\Strategy\ObjectCollection 7 | \DesignPatterns\Behavioral\Strategy\DateComparator 8 | \DesignPatterns\Behavioral\Strategy\ComparatorInterface 9 | \DesignPatterns\Behavioral\Strategy\IdComparator 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Fields 30 | Constants 31 | Constructors 32 | Methods 33 | 34 | private 35 | 36 | 37 | -------------------------------------------------------------------------------- /Behavioral/Strategy/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/Strategy/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/TemplateMethod/BeachJourney.php: -------------------------------------------------------------------------------- 1 | buyAFlight(); 19 | $this->takePlane(); 20 | $this->enjoyVacation(); 21 | $this->buyGift(); 22 | $this->takePlane(); 23 | } 24 | 25 | /** 26 | * This method must be implemented, this is the key-feature of this pattern 27 | */ 28 | abstract protected function enjoyVacation(); 29 | 30 | /** 31 | * This method is also part of the algorithm but it is optional. 32 | * This is an "adapter" (do not confuse with the Adapter pattern, not related) 33 | * You can override it only if you need to. 34 | */ 35 | protected function buyGift() 36 | { 37 | } 38 | 39 | /** 40 | * This method will be unknown by subclasses (better) 41 | */ 42 | private function buyAFlight() 43 | { 44 | echo "Buying a flight\n"; 45 | } 46 | 47 | /** 48 | * Subclasses will get access to this method but cannot override it and 49 | * compromise this algorithm (warning : cause of cyclic dependencies) 50 | */ 51 | final protected function takePlane() 52 | { 53 | echo "Taking the plane\n"; 54 | } 55 | 56 | // A note regarding the keyword "final" : don't use it when you start coding : 57 | // add it after you narrow and know exactly what change and what remain unchanged 58 | // in this algorithm. 59 | // [abstract] x [3 access] x [final] = 12 combinations, it can be hard ! 60 | } 61 | -------------------------------------------------------------------------------- /Behavioral/TemplateMethod/README.md: -------------------------------------------------------------------------------- 1 | # Template Method 2 | 3 | ## Propósito 4 | 5 | Permitir que subclasses de uma template abstrato "termine" o comportamento de 6 | um algoritmo. Também é conhecido como Princípio de Hollywood: "Não nos chame, 7 | nós chamamos você" ("Don't call us, we call you"). 8 | 9 | Essa classe não é chamada por subclasses; pelo contrário. Mas como? Com 10 | abstração, evidentemente. Em outras palavras, é um esqueleto do algoritmo, ideal 11 | para bibliotecas de frameworks. Quem está usando deve somente implementar um 12 | método e a superclasse faz o restante do serviço. 13 | 14 | Essa é uma maneira fácil de desacoplar classes concretas e reduzir o copiar-colar, 15 | e é por isso que você encontra esse Padrão por toda parte. 16 | 17 | ## Diagrama UML 18 | 19 | ![Alt TemplateMethod UML Diagram](uml/uml.png) 20 | -------------------------------------------------------------------------------- /Behavioral/TemplateMethod/Tests/JourneyTest.php: -------------------------------------------------------------------------------- 1 | expectOutputRegex('#sun-bathing#'); 17 | $journey->takeATrip(); 18 | } 19 | 20 | public function testCity() 21 | { 22 | $journey = new TemplateMethod\CityJourney(); 23 | $this->expectOutputRegex('#drink#'); 24 | $journey->takeATrip(); 25 | } 26 | 27 | /** 28 | * How to test an abstract template method with PHPUnit 29 | */ 30 | public function testLasVegas() 31 | { 32 | $journey = $this->getMockForAbstractClass('DesignPatterns\Behavioral\TemplateMethod\Journey'); 33 | $journey->expects($this->once()) 34 | ->method('enjoyVacation') 35 | ->will($this->returnCallback(array($this, 'mockUpVacation'))); 36 | $this->expectOutputRegex('#Las Vegas#'); 37 | $journey->takeATrip(); 38 | } 39 | 40 | public function mockUpVacation() 41 | { 42 | echo "Fear and loathing in Las Vegas\n"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Behavioral/TemplateMethod/uml/TemplateMethod.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\TemplateMethod\BeachJourney 5 | 6 | \DesignPatterns\Behavioral\TemplateMethod\CityJourney 7 | \DesignPatterns\Behavioral\TemplateMethod\Journey 8 | \DesignPatterns\Behavioral\TemplateMethod\BeachJourney 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Fields 29 | Constants 30 | Constructors 31 | Methods 32 | 33 | private 34 | 35 | 36 | -------------------------------------------------------------------------------- /Behavioral/TemplateMethod/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/TemplateMethod/uml/uml.png -------------------------------------------------------------------------------- /Behavioral/Visitor/Group.php: -------------------------------------------------------------------------------- 1 | name = (string) $name; 21 | } 22 | 23 | /** 24 | * @return string 25 | */ 26 | public function getName() 27 | { 28 | return "Group: " . $this->name; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Behavioral/Visitor/README.md: -------------------------------------------------------------------------------- 1 | # Visitor 2 | 3 | ## Propósito 4 | 5 | Permite terceirizar operações de objetos para outros objetos. A razão principal 6 | para se fazer isso é manter a separação de interesses. Mas classes têm de definir 7 | um "contrato" para permitir visitantes (o método `Role::accept` no exemplo). 8 | 9 | O contrato é uma classe abstrata, mas também é possível se ter uma interface. 10 | Nesse caso, cada Visitor (Visitante) deve escolher qual método invocar no 11 | visitante. 12 | 13 | ## Diagrama UML 14 | 15 | ![Alt Visitor UML Diagram](uml/uml.png) 16 | -------------------------------------------------------------------------------- /Behavioral/Visitor/Role.php: -------------------------------------------------------------------------------- 1 | getName(); 18 | } 19 | 20 | /** 21 | * {@inheritdoc} 22 | */ 23 | public function visitUser(User $role) 24 | { 25 | echo "Role: " . $role->getName(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Behavioral/Visitor/RoleVisitorInterface.php: -------------------------------------------------------------------------------- 1 | visitor = new Visitor\RolePrintVisitor(); 18 | } 19 | 20 | public function getRole() 21 | { 22 | return array( 23 | array(new Visitor\User("Dominik"), 'Role: User Dominik'), 24 | array(new Visitor\Group("Administrators"), 'Role: Group: Administrators') 25 | ); 26 | } 27 | 28 | /** 29 | * @dataProvider getRole 30 | */ 31 | public function testVisitSomeRole(Visitor\Role $role, $expect) 32 | { 33 | $this->expectOutputString($expect); 34 | $role->accept($this->visitor); 35 | } 36 | 37 | /** 38 | * @expectedException \InvalidArgumentException 39 | * @expectedExceptionMessage Mock 40 | */ 41 | public function testUnknownObject() 42 | { 43 | $mock = $this->getMockForAbstractClass('DesignPatterns\Behavioral\Visitor\Role'); 44 | $mock->accept($this->visitor); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Behavioral/Visitor/User.php: -------------------------------------------------------------------------------- 1 | name = (string) $name; 23 | } 24 | 25 | /** 26 | * @return string 27 | */ 28 | public function getName() 29 | { 30 | return "User " . $this->name; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Behavioral/Visitor/uml/Visitor.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Behavioral\Visitor\Group 5 | 6 | \DesignPatterns\Behavioral\Visitor\Role 7 | \DesignPatterns\Behavioral\Visitor\RolePrintVisitor 8 | \DesignPatterns\Behavioral\Visitor\Group 9 | \DesignPatterns\Behavioral\Visitor\RoleVisitorInterface 10 | \DesignPatterns\Behavioral\Visitor\User 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Fields 35 | Constants 36 | Constructors 37 | Methods 38 | 39 | private 40 | 41 | 42 | -------------------------------------------------------------------------------- /Behavioral/Visitor/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Behavioral/Visitor/uml/uml.png -------------------------------------------------------------------------------- /Creational/AbstractFactory/AbstractFactory.php: -------------------------------------------------------------------------------- 1 | ', $this->path, $this->name); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/Html/Text.php: -------------------------------------------------------------------------------- 1 | ' . htmlspecialchars($this->text) . ''; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/HtmlFactory.php: -------------------------------------------------------------------------------- 1 | $this->name, 'path' => $this->path)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/Json/Text.php: -------------------------------------------------------------------------------- 1 | $this->text)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/JsonFactory.php: -------------------------------------------------------------------------------- 1 | name = (string) $name; 28 | $this->path = (string) $path; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/README.md: -------------------------------------------------------------------------------- 1 | # Abstract Factory 2 | 3 | ## Propósito 4 | 5 | Criar séries de objetos correlatos ou dependentes sem especificar suas classes 6 | concretas. Geralmente todas as classes criadas implementam uma mesma interface. 7 | O cliente da Abstract Factory não se importa sobre como esses objetos são criados, 8 | apenas como eles interagem entre si. 9 | 10 | ## Diagrama UML 11 | 12 | ![Alt AbstractFactory UML Diagram](uml/uml.png) 13 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/Tests/AbstractFactoryTest.php: -------------------------------------------------------------------------------- 1 | createText('Lorem Ipsum'), 33 | $factory->createPicture('/image.jpg', 'caption'), 34 | $factory->createText('footnotes') 35 | ); 36 | 37 | $this->assertContainsOnly('DesignPatterns\Creational\AbstractFactory\MediaInterface', $article); 38 | 39 | /* this is the time to look at the Builder pattern. This pattern 40 | * helps you to create complex object like that article above with 41 | * a given Abstract Factory 42 | */ 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/Text.php: -------------------------------------------------------------------------------- 1 | text = (string) $text; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/uml/AbstractFactory.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Creational\AbstractFactory\AbstractFactory 5 | 6 | \DesignPatterns\Creational\AbstractFactory\Html\Text 7 | \DesignPatterns\Creational\AbstractFactory\Html\Picture 8 | \DesignPatterns\Creational\AbstractFactory\HtmlFactory 9 | \DesignPatterns\Creational\AbstractFactory\JsonFactory 10 | \DesignPatterns\Creational\AbstractFactory\AbstractFactory 11 | \DesignPatterns\Creational\AbstractFactory\MediaInterface 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Fields 32 | Constants 33 | Constructors 34 | Methods 35 | 36 | private 37 | 38 | 39 | -------------------------------------------------------------------------------- /Creational/AbstractFactory/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Creational/AbstractFactory/uml/uml.png -------------------------------------------------------------------------------- /Creational/Builder/BikeBuilder.php: -------------------------------------------------------------------------------- 1 | bike->setPart('engine', new Parts\Engine()); 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function addWheel() 35 | { 36 | $this->bike->setPart('forwardWheel', new Parts\Wheel()); 37 | $this->bike->setPart('rearWheel', new Parts\Wheel()); 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | */ 43 | public function createVehicle() 44 | { 45 | $this->bike = new Parts\Bike(); 46 | } 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | public function getVehicle() 52 | { 53 | return $this->bike; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Creational/Builder/BuilderInterface.php: -------------------------------------------------------------------------------- 1 | car->setPart('rightdoor', new Parts\Door()); 21 | $this->car->setPart('leftDoor', new Parts\Door()); 22 | } 23 | 24 | /** 25 | * @return void 26 | */ 27 | public function addEngine() 28 | { 29 | $this->car->setPart('engine', new Parts\Engine()); 30 | } 31 | 32 | /** 33 | * @return void 34 | */ 35 | public function addWheel() 36 | { 37 | $this->car->setPart('wheelLF', new Parts\Wheel()); 38 | $this->car->setPart('wheelRF', new Parts\Wheel()); 39 | $this->car->setPart('wheelLR', new Parts\Wheel()); 40 | $this->car->setPart('wheelRR', new Parts\Wheel()); 41 | } 42 | 43 | /** 44 | * @return void 45 | */ 46 | public function createVehicle() 47 | { 48 | $this->car = new Parts\Car(); 49 | } 50 | 51 | /** 52 | * @return Parts\Car 53 | */ 54 | public function getVehicle() 55 | { 56 | return $this->car; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Creational/Builder/Director.php: -------------------------------------------------------------------------------- 1 | createVehicle(); 24 | $builder->addDoors(); 25 | $builder->addEngine(); 26 | $builder->addWheel(); 27 | 28 | return $builder->getVehicle(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Creational/Builder/Parts/Bike.php: -------------------------------------------------------------------------------- 1 | data[$key] = $value; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Creational/Builder/Parts/Wheel.php: -------------------------------------------------------------------------------- 1 | director = new Director(); 21 | } 22 | 23 | public function getBuilder() 24 | { 25 | return array( 26 | array(new CarBuilder()), 27 | array(new BikeBuilder()) 28 | ); 29 | } 30 | 31 | /** 32 | * Here we test the build process. Notice that the client don't know 33 | * anything about the contrete builder. 34 | * 35 | * @dataProvider getBuilder 36 | */ 37 | public function testBuild(BuilderInterface $builder) 38 | { 39 | $newVehicle = $this->director->build($builder); 40 | $this->assertInstanceOf('DesignPatterns\Creational\Builder\Parts\Vehicle', $newVehicle); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Creational/Builder/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Creational/Builder/uml/uml.png -------------------------------------------------------------------------------- /Creational/FactoryMethod/Bicycle.php: -------------------------------------------------------------------------------- 1 | color = $rgb; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Creational/FactoryMethod/FactoryMethod.php: -------------------------------------------------------------------------------- 1 | createVehicle($type); 35 | $obj->setColor("#f00"); 36 | 37 | return $obj; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Creational/FactoryMethod/Ferrari.php: -------------------------------------------------------------------------------- 1 | color = $rgb; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Creational/FactoryMethod/GermanFactory.php: -------------------------------------------------------------------------------- 1 | addTuningAMG(); 24 | 25 | return $obj; 26 | break; 27 | default: 28 | throw new \InvalidArgumentException("$type is not a valid vehicle"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Creational/FactoryMethod/ItalianFactory.php: -------------------------------------------------------------------------------- 1 | color = $rgb; 21 | } 22 | 23 | /** 24 | * although tuning by AMG is only offered for Mercedes Cars, 25 | * this is a valid coding example ... 26 | */ 27 | public function addTuningAMG() 28 | { 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Creational/FactoryMethod/README.md: -------------------------------------------------------------------------------- 1 | # Factory Method 2 | 3 | ## Propósito 4 | 5 | O bom do SimpleFactory é que você pode "subclasseá-lo" para implementar diferentes 6 | maneiras de criar objetos. 7 | 8 | Para casos simples, essa classe abstrata poderia ser apenas uma internface. 9 | 10 | Esse Padrão é um Padrão de Projeto "real" porque está consonante ao Princípio da 11 | Inversão de Dependência (Dependency Inversion Principle), o "D" dos princípios 12 | S.O.L.I.D. 13 | 14 | Isso significa que a classe FactoryMethod depende de abstrações, não de classes 15 | concretas. Esse é o verdadeiro "truque" comparado a Simple Factory ou Static 16 | Factory. 17 | 18 | ## Diagrama UML 19 | 20 | ![Alt FactoryMethod UML Diagram](uml/uml.png) 21 | -------------------------------------------------------------------------------- /Creational/FactoryMethod/Tests/FactoryMethodTest.php: -------------------------------------------------------------------------------- 1 | type as $oneType) { 36 | $vehicle = $shop->create($oneType); 37 | $this->assertInstanceOf('DesignPatterns\Creational\FactoryMethod\VehicleInterface', $vehicle); 38 | } 39 | } 40 | 41 | /** 42 | * @dataProvider getShop 43 | * @expectedException \InvalidArgumentException 44 | * @expectedExceptionMessage spaceship is not a valid vehicle 45 | */ 46 | public function testUnknownType(FactoryMethod $shop) 47 | { 48 | $shop->create('spaceship'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Creational/FactoryMethod/VehicleInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Creational\Multiton\Multiton 5 | 6 | \DesignPatterns\Creational\Multiton\Multiton 7 | 8 | 9 | 10 | 11 | 12 | 13 | Fields 14 | Constants 15 | Constructors 16 | Methods 17 | 18 | private 19 | 20 | 21 | -------------------------------------------------------------------------------- /Creational/Multiton/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Creational/Multiton/uml/uml.png -------------------------------------------------------------------------------- /Creational/Pool/Pool.php: -------------------------------------------------------------------------------- 1 | class = $class; 14 | } 15 | 16 | public function get() 17 | { 18 | if (count($this->instances) > 0) { 19 | return array_pop($this->instances); 20 | } 21 | 22 | return new $this->class(); 23 | } 24 | 25 | public function dispose($instance) 26 | { 27 | $this->instances[] = $instance; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Creational/Pool/Processor.php: -------------------------------------------------------------------------------- 1 | pool = $pool; 16 | } 17 | 18 | public function process($image) 19 | { 20 | if ($this->processing++ < $this->maxProcesses) { 21 | $this->createWorker($image); 22 | } else { 23 | $this->pushToWaitingQueue($image); 24 | } 25 | } 26 | 27 | private function createWorker($image) 28 | { 29 | $worker = $this->pool->get(); 30 | $worker->run($image, array($this, 'processDone')); 31 | } 32 | 33 | public function processDone($worker) 34 | { 35 | $this->processing--; 36 | $this->pool->dispose($worker); 37 | 38 | if (count($this->waitingQueue) > 0) { 39 | $this->createWorker($this->popFromWaitingQueue()); 40 | } 41 | } 42 | 43 | private function pushToWaitingQueue($image) 44 | { 45 | $this->waitingQueue[] = $image; 46 | } 47 | 48 | private function popFromWaitingQueue() 49 | { 50 | return array_pop($this->waitingQueue); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Creational/Pool/README.md: -------------------------------------------------------------------------------- 1 | Pool 2 | ==== 3 | 4 | ## Propósito 5 | 6 | Ser um Padrão de Projeto que usa uma série de objetos 7 | inicializados mantidos prontos para uso -- uma "pool" (poço, tanque) -- ao invés 8 | de os instânciar e destruir conforme a demanda. Um cliente requererá um objeto da 9 | poll e fará operações neste objeto retornado. Quando o cliente tiver terminado, 10 | retornará o objeto -- que é um tipo específico de objeto "factory" -- para a poll 11 | ao invés de destruí-lo. 12 | 13 | Usar este Padrão pode oferecer uma melhoria significativa de performance em 14 | situações em que o custo de inicializar um objeto é alto, a taxa de instânciação 15 | é alta e o número de instâncias em uso a qualquer momento é baixo. O objeto 16 | retirado da poll é obtido em um tempo previsível quando a criação de novos 17 | objetos (especialmente através da rede) pode levar algum tempo. 18 | 19 | Entretanto, esses benefícios são em sua maioria verdadeiros para objetos que são 20 | dispendiosos em relação ao tempo, tal como conexões a BDs, conexões a sockets, 21 | threads e grandes objetos de gráficos como fontes e bitmaps. Em certas situações, 22 | "object pooling" (que não armazena nenhum recurso externo, mas ocupa memória) 23 | pode não ser eficiente e pode ocasionar decréscimo de performance. 24 | 25 | ## Diagrama UML 26 | 27 | ![Alt Pool UML Diagram](uml/uml.png) 28 | -------------------------------------------------------------------------------- /Creational/Pool/Tests/PoolTest.php: -------------------------------------------------------------------------------- 1 | get(); 19 | 20 | $this->assertEquals(1, $worker->id); 21 | 22 | $worker->id = 5; 23 | $pool->dispose($worker); 24 | 25 | $this->assertEquals(5, $pool->get()->id); 26 | $this->assertEquals(1, $pool->get()->id); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Creational/Pool/Worker.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Creational\Pool\Processor 5 | 6 | \DesignPatterns\Creational\Pool\Pool 7 | \DesignPatterns\Creational\Pool\Processor 8 | \DesignPatterns\Creational\Pool\Worker 9 | 10 | 11 | 12 | 13 | 14 | 15 | Fields 16 | Constants 17 | Constructors 18 | Methods 19 | 20 | private 21 | 22 | 23 | -------------------------------------------------------------------------------- /Creational/Pool/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Creational/Pool/uml/uml.png -------------------------------------------------------------------------------- /Creational/Prototype/BarBookPrototype.php: -------------------------------------------------------------------------------- 1 | title; 32 | } 33 | 34 | /** 35 | * @param string $title 36 | */ 37 | public function setTitle($title) 38 | { 39 | $this->title = $title; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Creational/Prototype/FooBookPrototype.php: -------------------------------------------------------------------------------- 1 | setTitle('Foo Book No ' . $i); 12 | } 13 | 14 | for ($i = 0; $i < 5000; $i++) { 15 | $book = clone $barPrototype; 16 | $book->setTitle('Bar Book No ' . $i); 17 | } 18 | -------------------------------------------------------------------------------- /Creational/Prototype/uml/Prototype.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Creational\Prototype\BarBookPrototype 5 | 6 | \DesignPatterns\Creational\Prototype\BookPrototype 7 | \DesignPatterns\Creational\Prototype\FooBookPrototype 8 | \DesignPatterns\Creational\Prototype\BarBookPrototype 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Fields 29 | Constants 30 | Constructors 31 | Methods 32 | 33 | private 34 | 35 | 36 | -------------------------------------------------------------------------------- /Creational/Prototype/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Creational/Prototype/uml/uml.png -------------------------------------------------------------------------------- /Creational/README.md: -------------------------------------------------------------------------------- 1 | # Criacional 2 | 3 | Em Engenharia de Software, Padrões de Projeto Criacionais são os que lidam com 4 | os mecanismos de criação de objetos, tentando criá-los de uma maneira adequada 5 | a cada situação. A forma básica de criação de objeto pode resultar em problemas 6 | de design ou acrescentar complexidade adicional ao design. Padrões de Projeto 7 | Criacionais resolvem este problema ao controlar a forma como objetos são criados. 8 | 9 | * [AbstractFactory](AbstractFactory) [:notebook:](http://pt.wikipedia.org/wiki/Abstract_Factory) 10 | * [Builder](Builder) [:notebook:](http://pt.wikipedia.org/wiki/Builder) 11 | * [FactoryMethod](FactoryMethod) [:notebook:](http://pt.wikipedia.org/wiki/Factory_Method) 12 | * [Multiton](Multiton) (considerado um anti-pattern! :no_entry:) 13 | * [Pool](Pool) [:notebook:](http://en.wikipedia.org/wiki/Object_pool_pattern) 14 | * [Prototype](Prototype) [:notebook:](http://pt.wikipedia.org/wiki/Prototype) 15 | * [SimpleFactory](SimpleFactory) 16 | * [Singleton](Singleton) [:notebook:](http://pt.wikipedia.org/wiki/Singleton) (considerado um anti-pattern! :no_entry:) 17 | * [StaticFactory](StaticFactory) 18 | -------------------------------------------------------------------------------- /Creational/SimpleFactory/Bicycle.php: -------------------------------------------------------------------------------- 1 | typeList = array( 22 | 'bicycle' => __NAMESPACE__ . '\Bicycle', 23 | 'other' => __NAMESPACE__ . '\Scooter' 24 | ); 25 | } 26 | 27 | /** 28 | * Creates a vehicle 29 | * 30 | * @param string $type a known type key 31 | * 32 | * @return VehicleInterface a new instance of VehicleInterface 33 | * @throws \InvalidArgumentException 34 | */ 35 | public function createVehicle($type) 36 | { 37 | if (!array_key_exists($type, $this->typeList)) { 38 | throw new \InvalidArgumentException("$type is not valid vehicle"); 39 | } 40 | $className = $this->typeList[$type]; 41 | 42 | return new $className(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Creational/SimpleFactory/README.md: -------------------------------------------------------------------------------- 1 | # Simple Factory 2 | 3 | ## Propósito 4 | 5 | Concrete Factory é um Padrão simples de factory (fábrica). 6 | 7 | Difere da Static Factory porque NÃO É estático e, como você sabe, `static` => 8 | `global` => evil! 9 | 10 | Portanto, você pode ter múltiplas factories diferentemente parametrizadas, pode 11 | "subclassear" e pode usar mockups. 12 | 13 | ## Diagrama UML 14 | 15 | ![Alt SimpleFactory UML Diagram](uml/uml.png) 16 | -------------------------------------------------------------------------------- /Creational/SimpleFactory/Scooter.php: -------------------------------------------------------------------------------- 1 | factory = new ConcreteFactory(); 18 | } 19 | 20 | public function getType() 21 | { 22 | return array( 23 | array('bicycle'), 24 | array('other') 25 | ); 26 | } 27 | 28 | /** 29 | * @dataProvider getType 30 | */ 31 | public function testCreation($type) 32 | { 33 | $obj = $this->factory->createVehicle($type); 34 | $this->assertInstanceOf('DesignPatterns\Creational\SimpleFactory\VehicleInterface', $obj); 35 | } 36 | 37 | /** 38 | * @expectedException \InvalidArgumentException 39 | */ 40 | public function testBadType() 41 | { 42 | $this->factory->createVehicle('car'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Creational/SimpleFactory/VehicleInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Creational\SimpleFactory\ConcreteFactory 5 | 6 | \DesignPatterns\Creational\SimpleFactory\Scooter 7 | \DesignPatterns\Creational\SimpleFactory\ConcreteFactory 8 | \DesignPatterns\Creational\SimpleFactory\VehicleInterface 9 | \DesignPatterns\Creational\SimpleFactory\Bicycle 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Fields 30 | Constants 31 | Constructors 32 | Methods 33 | 34 | private 35 | 36 | 37 | -------------------------------------------------------------------------------- /Creational/SimpleFactory/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Creational/SimpleFactory/uml/uml.png -------------------------------------------------------------------------------- /Creational/Singleton/README.md: -------------------------------------------------------------------------------- 1 | # Singleton 2 | 3 | **ISSO É CONSIDERADO UM ANTI-PATTERN! PARA UMA MELHOR TESTABILIDADE E 4 | MANTENIBILIDADE, USE INJEÇÃO DE DEPENDÊNCIA!** 5 | 6 | # Propósito 7 | 8 | Ter apenas uma instância de um objeto na aplicação que irá lidar com as chamadas. 9 | 10 | ## Exemplos 11 | 12 | * DB Connector 13 | * Logger (também pode ser um Multiton se houver vários arquivos de log para vários 14 | propósitos diferentes 15 | * Travar um arquivo para a aplicação (há somente um no sistema de arquivos...) 16 | 17 | ## Diagrama UML 18 | 19 | ![Alt Singleton UML Diagram](uml/uml.png) 20 | -------------------------------------------------------------------------------- /Creational/Singleton/Singleton.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('DesignPatterns\Creational\Singleton\Singleton', $firstCall); 17 | $secondCall = Singleton::getInstance(); 18 | $this->assertSame($firstCall, $secondCall); 19 | } 20 | 21 | public function testNoConstructor() 22 | { 23 | $obj = Singleton::getInstance(); 24 | 25 | $refl = new \ReflectionObject($obj); 26 | $meth = $refl->getMethod('__construct'); 27 | $this->assertTrue($meth->isPrivate()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Creational/Singleton/uml/Singleton.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Creational\Singleton\Singleton 5 | 6 | \DesignPatterns\Creational\Singleton\Singleton 7 | 8 | 9 | 10 | 11 | 12 | 13 | Fields 14 | Constants 15 | Constructors 16 | Methods 17 | 18 | private 19 | 20 | 21 | -------------------------------------------------------------------------------- /Creational/Singleton/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Creational/Singleton/uml/uml.png -------------------------------------------------------------------------------- /Creational/StaticFactory/FormatNumber.php: -------------------------------------------------------------------------------- 1 | global => evil 7 | * Note2: Cannot be subclassed or mock-upped or have multiple different instances 8 | */ 9 | class StaticFactory 10 | { 11 | /** 12 | * the parametrized function to get create an instance 13 | * 14 | * @param string $type 15 | * 16 | * @static 17 | * 18 | * @throws \InvalidArgumentException 19 | * @return FormatterInterface 20 | */ 21 | public static function factory($type) 22 | { 23 | $className = __NAMESPACE__ . '\Format' . ucfirst($type); 24 | 25 | if (!class_exists($className)) { 26 | throw new \InvalidArgumentException('Missing format class.'); 27 | } 28 | 29 | return new $className(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Creational/StaticFactory/Tests/StaticFactoryTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('DesignPatterns\Creational\StaticFactory\FormatterInterface', $obj); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Creational/StaticFactory/uml/StaticFactory.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Creational\StaticFactory\FormatNumber 5 | 6 | \DesignPatterns\Creational\StaticFactory\FormatNumber 7 | \DesignPatterns\Creational\StaticFactory\StaticFactory 8 | \DesignPatterns\Creational\StaticFactory\FormatString 9 | \DesignPatterns\Creational\StaticFactory\FormatterInterface 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Fields 30 | Constants 31 | Constructors 32 | Methods 33 | 34 | private 35 | 36 | 37 | -------------------------------------------------------------------------------- /Creational/StaticFactory/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Creational/StaticFactory/uml/uml.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Dominik Liebler 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /More/Delegation/JuniorDeveloper.php: -------------------------------------------------------------------------------- 1 | slave = $junior; 22 | } 23 | 24 | /** 25 | * TeamLead drink coffee, junior work 26 | * @return mixed 27 | */ 28 | public function writeCode() 29 | { 30 | return $this->slave->writeBadCode(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /More/Delegation/Tests/DelegationTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($junior->writeBadCode(), $teamLead->writeCode()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /More/Delegation/Usage.php: -------------------------------------------------------------------------------- 1 | writeCode(); 10 | -------------------------------------------------------------------------------- /More/Delegation/uml/Delegation.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\More\Delegation\JuniorDeveloper 5 | 6 | \DesignPatterns\More\Delegation\JuniorDeveloper 7 | \DesignPatterns\More\Delegation\TeamLead 8 | 9 | 10 | 11 | 12 | 13 | 14 | Fields 15 | Constants 16 | Constructors 17 | Methods 18 | 19 | private 20 | 21 | 22 | -------------------------------------------------------------------------------- /More/Delegation/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/More/Delegation/uml/uml.png -------------------------------------------------------------------------------- /More/README.md: -------------------------------------------------------------------------------- 1 | # Mais 2 | 3 | * [Delegation](Delegation) [:notebook:](http://en.wikipedia.org/wiki/Delegation_pattern) 4 | * [ServiceLocator](ServiceLocator) [:notebook:](http://en.wikipedia.org/wiki/Service_locator_pattern) 5 | * [Repository](Repository) 6 | -------------------------------------------------------------------------------- /More/Repository/MemoryStorage.php: -------------------------------------------------------------------------------- 1 | data = array(); 18 | $this->lastId = 0; 19 | } 20 | 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function persist($data) 25 | { 26 | $this->data[++$this->lastId] = $data; 27 | return $this->lastId; 28 | } 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | public function retrieve($id) 34 | { 35 | return isset($this->data[$id]) ? $this->data[$id] : null; 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function delete($id) 42 | { 43 | if(!isset($this->data[$id])){ 44 | return false; 45 | } 46 | 47 | $this->data[$id] = null; 48 | unset($this->data[$id]); 49 | 50 | return true; 51 | } 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /More/Repository/README.md: -------------------------------------------------------------------------------- 1 | # Repository 2 | 3 | ## Propósito 4 | 5 | Fazer a mediação entre domínio e camadas de data mapping usando interfaces tipo 6 | coleção para acessar objetos de domínio. 7 | 8 | Esse Padrão encapsula o conjunto de objetos persistidos em armazenamento de dados 9 | e as operações feitas nele, provendo uma visão mais orientada a objetos da 10 | camada de persistência. 11 | 12 | Repository também suporta o objetivo de alcançar uma separação clara e dependência 13 | de mão única entre o domínio e camadas de data mapping. 14 | 15 | ## Exemplos 16 | 17 | * Doctrine2 ORM: há um Repository que faz a mediação entre Entity e DBAL e 18 | contém métodos para retornar objetos 19 | * Framework Laravel 20 | 21 | ## Diagrama UML 22 | 23 | ![Alt Repository UML Diagram](uml/uml.png) 24 | -------------------------------------------------------------------------------- /More/Repository/Storage.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Repository\PostRepository 5 | 6 | \DesignPatterns\Repository\Storage 7 | \DesignPatterns\Repository\MemoryStorage 8 | \DesignPatterns\Repository\Post 9 | \DesignPatterns\Repository\PostRepository 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Fields 22 | Constants 23 | Constructors 24 | Methods 25 | 26 | private 27 | 28 | 29 | -------------------------------------------------------------------------------- /More/Repository/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/More/Repository/uml/uml.png -------------------------------------------------------------------------------- /More/ServiceLocator/DatabaseService.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\More\ServiceLocator\DatabaseServiceInterface 5 | 6 | \DesignPatterns\More\ServiceLocator\DatabaseServiceInterface 7 | \DesignPatterns\More\ServiceLocator\LogService 8 | \DesignPatterns\More\ServiceLocator\ServiceLocator 9 | \DesignPatterns\More\ServiceLocator\ServiceLocatorInterface 10 | \DesignPatterns\More\ServiceLocator\LogServiceInterface 11 | \DesignPatterns\More\ServiceLocator\DatabaseService 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Fields 32 | Constants 33 | Constructors 34 | Methods 35 | 36 | private 37 | 38 | 39 | -------------------------------------------------------------------------------- /More/ServiceLocator/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/More/ServiceLocator/uml/uml.png -------------------------------------------------------------------------------- /Structural/Adapter/Book.php: -------------------------------------------------------------------------------- 1 | eBook = $ebook; 26 | } 27 | 28 | /** 29 | * This class makes the proper translation from one interface to another 30 | */ 31 | public function open() 32 | { 33 | $this->eBook->pressStart(); 34 | } 35 | 36 | /** 37 | * turns pages 38 | */ 39 | public function turnPage() 40 | { 41 | $this->eBook->pressNext(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Structural/Adapter/EBookInterface.php: -------------------------------------------------------------------------------- 1 | open(); 39 | $book->turnPage(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Structural/Adapter/uml/Adapter.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Structural\Adapter\Book 5 | 6 | \DesignPatterns\Structural\Adapter\EBookAdapter 7 | \DesignPatterns\Structural\Adapter\Book 8 | \DesignPatterns\Structural\Adapter\Kindle 9 | \DesignPatterns\Structural\Adapter\EBookInterface 10 | \DesignPatterns\Structural\Adapter\PaperBookInterface 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Fields 35 | Constants 36 | Constructors 37 | Methods 38 | 39 | private 40 | 41 | 42 | -------------------------------------------------------------------------------- /Structural/Adapter/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Structural/Adapter/uml/uml.png -------------------------------------------------------------------------------- /Structural/Bridge/Assemble.php: -------------------------------------------------------------------------------- 1 | workShop1->work(); 20 | $this->workShop2->work(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Structural/Bridge/Motorcycle.php: -------------------------------------------------------------------------------- 1 | workShop1->work(); 20 | $this->workShop2->work(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Structural/Bridge/Produce.php: -------------------------------------------------------------------------------- 1 | expectOutputString('Car Produced Assembled'); 17 | $vehicle->manufacture(); 18 | } 19 | 20 | public function testMotorcycle() 21 | { 22 | $vehicle = new Motorcycle(new Produce(), new Assemble()); 23 | $this->expectOutputString('Motorcycle Produced Assembled'); 24 | $vehicle->manufacture(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Structural/Bridge/Vehicle.php: -------------------------------------------------------------------------------- 1 | workShop1 = $workShop1; 17 | $this->workShop2 = $workShop2; 18 | } 19 | 20 | public function manufacture() 21 | { 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Structural/Bridge/Workshop.php: -------------------------------------------------------------------------------- 1 | elements as $element) { 31 | $formCode .= $element->render($indent + 1) . PHP_EOL; 32 | } 33 | 34 | return $formCode; 35 | } 36 | 37 | /** 38 | * @param FormElement $element 39 | */ 40 | public function addElement(FormElement $element) 41 | { 42 | $this->elements[] = $element; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Structural/Composite/FormElement.php: -------------------------------------------------------------------------------- 1 | '; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Structural/Composite/README.md: -------------------------------------------------------------------------------- 1 | # Composite 2 | 3 | ## Propósito 4 | 5 | Tratar um grupo de objetos da mesma maneira, como se fossem uma instância de um 6 | único objeto. 7 | 8 | ## Exemplos 9 | 10 | * Uma instância de uma classe de formulário lida com todos seus elementos como 11 | se uma única instância desse formumário, quando `render()` é chamado, ele 12 | subsequentemente roda através de todos seus elementos-filhos e chama `render()` 13 | neles 14 | * `Zend_Config`: uma árvore de opções de configuração, cada uma é um objeto `Zend_Config` 15 | 16 | ## Diagrama UML 17 | 18 | ![Alt Composite UML Diagram](uml/uml.png) 19 | -------------------------------------------------------------------------------- /Structural/Composite/Tests/CompositeTest.php: -------------------------------------------------------------------------------- 1 | addElement(new Composite\TextElement()); 17 | $form->addElement(new Composite\InputElement()); 18 | $embed = new Composite\Form(); 19 | $embed->addElement(new Composite\TextElement()); 20 | $embed->addElement(new Composite\InputElement()); 21 | $form->addElement($embed); // here we have a embedded form (like SF2 does) 22 | 23 | $this->assertRegExp('#^\s{4}#m', $form->render()); 24 | } 25 | 26 | /** 27 | * The all point of this pattern, a Composite must inherit from the node 28 | * if you want to builld trees 29 | */ 30 | public function testFormImplementsFormEelement() 31 | { 32 | $className = 'DesignPatterns\Structural\Composite\Form'; 33 | $abstractName = 'DesignPatterns\Structural\Composite\FormElement'; 34 | $this->assertTrue(is_subclass_of($className, $abstractName)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Structural/Composite/TextElement.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Structural\Composite\InputElement 5 | 6 | \DesignPatterns\Structural\Composite\TextElement 7 | \DesignPatterns\Structural\Composite\FormElement 8 | \DesignPatterns\Structural\Composite\InputElement 9 | \DesignPatterns\Structural\Composite\Form 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | \DesignPatterns\Structural\Composite\InputElement 33 | 34 | 35 | Fields 36 | Constants 37 | Constructors 38 | Methods 39 | 40 | private 41 | 42 | 43 | -------------------------------------------------------------------------------- /Structural/Composite/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Structural/Composite/uml/uml.png -------------------------------------------------------------------------------- /Structural/Composite/uml/uml.txt: -------------------------------------------------------------------------------- 1 | @startuml 2 | class Form { 3 | #elements : array|FormElement[] 4 | +render($indent = 0 : int) 5 | +addElement(FormElement $element) 6 | } 7 | 8 | abstract class FormElement { 9 | +render($indent = 0 : int) 10 | } 11 | 12 | class InputElement { 13 | +render($indent = 0 : int) 14 | } 15 | 16 | class TextElement { 17 | +render($indent = 0 : int) 18 | } 19 | 20 | FormElement <|.. TextElement 21 | FormElement <|.. InputElement 22 | FormElement <|.. Form 23 | @enduml -------------------------------------------------------------------------------- /Structural/DataMapper/README.md: -------------------------------------------------------------------------------- 1 | # Data Mapper 2 | 3 | ## Propósito 4 | 5 | Um Data Mapper é uma camada de acesso a dados que realiza transferências 6 | bidirecionais e dados entre uma cama de persistência (geralmente um Banco de 7 | Dados Relacional) e uma representação de dados em memória (a camada de domínio). 8 | O objetivo desse Padrão é manter a representação de dados em memória e a camada 9 | de persistência de dados independentes uma da outra e do próprio Data Mapper. 10 | 11 | A camada é composta por um ou mais mappers -- ou Data Access Objects (Objetos de 12 | Acesso a Dados) -- fazendo a transferência de dados. Cada implementação de um 13 | mapper varia em escopo: mappers genéricos lidarão com vários tipos diferentes de 14 | entidades de domínio; mappers dedicados lidarão com um ou alguns. 15 | 16 | A chave desse Padrão -- diferentemente do Active Record -- é fazer com que o 17 | modelo de dados (data model) siga o Princípio da Responsabilidade Única do 18 | S.O.L.I.D. 19 | 20 | ## Exemplos 21 | 22 | * DB Object Relational Mapper (ORM): Doctrine2 usa um DAO chamado "EntityRepository" 23 | 24 | ## Diagrama UML 25 | 26 | ![Alt DataMapper UML Diagram](uml/uml.png) 27 | -------------------------------------------------------------------------------- /Structural/DataMapper/User.php: -------------------------------------------------------------------------------- 1 | userId = $id; 38 | $this->username = $username; 39 | $this->email = $email; 40 | } 41 | 42 | /** 43 | * @return int 44 | */ 45 | public function getUserId() 46 | { 47 | return $this->userId; 48 | } 49 | 50 | /** 51 | * @param int $userId 52 | */ 53 | public function setUserID($userId) 54 | { 55 | $this->userId = $userId; 56 | } 57 | 58 | /** 59 | * @return string 60 | */ 61 | public function getUsername() 62 | { 63 | return $this->username; 64 | } 65 | 66 | /** 67 | * @param string $username 68 | */ 69 | public function setUsername($username) 70 | { 71 | $this->username = $username; 72 | } 73 | 74 | /** 75 | * @return string 76 | */ 77 | public function getEmail() 78 | { 79 | return $this->email; 80 | } 81 | 82 | /** 83 | * @param string $email 84 | */ 85 | public function setEmail($email) 86 | { 87 | $this->email = $email; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Structural/DataMapper/uml/DataMapper.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Structural\DataMapper\User 5 | 6 | \DesignPatterns\Structural\DataMapper\User 7 | \DesignPatterns\Structural\DataMapper\UserMapper 8 | 9 | 10 | 11 | 12 | 13 | \DesignPatterns\Structural\DataMapper\User 14 | 15 | 16 | Fields 17 | Constants 18 | Constructors 19 | Methods 20 | 21 | private 22 | 23 | 24 | -------------------------------------------------------------------------------- /Structural/DataMapper/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Structural/DataMapper/uml/uml.png -------------------------------------------------------------------------------- /Structural/Decorator/Decorator.php: -------------------------------------------------------------------------------- 1 | wrapped = $wrappable; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Structural/Decorator/README.md: -------------------------------------------------------------------------------- 1 | # Decorator 2 | 3 | ## Propósito 4 | 5 | Dinamicamente adicionar novas funcionalidades a instância de classes. 6 | 7 | ## Exemplos 8 | 9 | * Zend Framework: decorators para instâncias de `Zend_Form_Element` 10 | * Web Service Layer: Decorators JSON e XML para um serviço REST (nesse caso, 11 | obviamente apenas um desses deve ser permitido) 12 | 13 | ## Diagrama UML 14 | 15 | ![Alt Decorator UML Diagram](uml/uml.png) 16 | -------------------------------------------------------------------------------- /Structural/Decorator/RenderInJson.php: -------------------------------------------------------------------------------- 1 | wrapped->renderData(); 18 | 19 | return json_encode($output); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Structural/Decorator/RenderInXml.php: -------------------------------------------------------------------------------- 1 | wrapped->renderData(); 18 | 19 | // do some fancy conversion to xml from array ... 20 | 21 | $doc = new \DOMDocument(); 22 | 23 | foreach ($output as $key => $val) { 24 | $doc->appendChild($doc->createElement($key, $val)); 25 | } 26 | 27 | return $doc->saveXML(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Structural/Decorator/RendererInterface.php: -------------------------------------------------------------------------------- 1 | data = $data; 21 | } 22 | 23 | /** 24 | * @return string 25 | */ 26 | public function renderData() 27 | { 28 | return $this->data; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Structural/Decorator/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Structural/Decorator/uml/uml.png -------------------------------------------------------------------------------- /Structural/DependencyInjection/AbstractConfig.php: -------------------------------------------------------------------------------- 1 | storage = $storage; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Structural/DependencyInjection/ArrayConfig.php: -------------------------------------------------------------------------------- 1 | storage[$key])) { 22 | return $this->storage[$key]; 23 | } 24 | return $default; 25 | } 26 | 27 | /** 28 | * Set parameter 29 | * 30 | * @param string|int $key 31 | * @param mixed $value 32 | */ 33 | public function set($key, $value) 34 | { 35 | $this->storage[$key] = $value; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Structural/DependencyInjection/Connection.php: -------------------------------------------------------------------------------- 1 | configuration = $config; 26 | } 27 | 28 | /** 29 | * connection using the injected config 30 | */ 31 | public function connect() 32 | { 33 | $host = $this->configuration->get('host'); 34 | // connection to host, authentication etc... 35 | 36 | //if connected 37 | $this->host = $host; 38 | } 39 | 40 | /* 41 | * Get currently connected host 42 | * 43 | * @return string 44 | */ 45 | public function getHost() 46 | { 47 | return $this->host; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Structural/DependencyInjection/Parameters.php: -------------------------------------------------------------------------------- 1 | source = include 'config.php'; 16 | $this->config = new ArrayConfig($this->source); 17 | } 18 | 19 | public function testDependencyInjection() 20 | { 21 | $connection = new Connection($this->config); 22 | $connection->connect(); 23 | $this->assertEquals($this->source['host'], $connection->getHost()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Structural/DependencyInjection/Tests/config.php: -------------------------------------------------------------------------------- 1 | 'github.com'); 4 | -------------------------------------------------------------------------------- /Structural/DependencyInjection/uml/DependencyInjection.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Structural\DependencyInjection\AbstractConfig 5 | 6 | \DesignPatterns\Structural\DependencyInjection\Connection 7 | \DesignPatterns\Structural\DependencyInjection\ArrayConfig 8 | \DesignPatterns\Structural\DependencyInjection\Parameters 9 | \DesignPatterns\Structural\DependencyInjection\AbstractConfig 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | \DesignPatterns\Structural\DependencyInjection\AbstractConfig 29 | 30 | 31 | Fields 32 | Constants 33 | Constructors 34 | Methods 35 | 36 | private 37 | 38 | 39 | -------------------------------------------------------------------------------- /Structural/DependencyInjection/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Structural/DependencyInjection/uml/uml.png -------------------------------------------------------------------------------- /Structural/Facade/BiosInterface.php: -------------------------------------------------------------------------------- 1 | bios = $bios; 31 | $this->os = $os; 32 | } 33 | 34 | /** 35 | * turn on the system 36 | */ 37 | public function turnOn() 38 | { 39 | $this->bios->execute(); 40 | $this->bios->waitForKeyPress(); 41 | $this->bios->launch($this->os); 42 | } 43 | 44 | /** 45 | * turn off the system 46 | */ 47 | public function turnOff() 48 | { 49 | $this->os->halt(); 50 | $this->bios->powerDown(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Structural/Facade/OsInterface.php: -------------------------------------------------------------------------------- 1 | getMockBuilder('DesignPatterns\Structural\Facade\BiosInterface') 16 | ->setMethods(array('launch', 'execute', 'waitForKeyPress')) 17 | ->disableAutoload() 18 | ->getMock(); 19 | $operatingSys = $this->getMockBuilder('DesignPatterns\Structural\Facade\OsInterface') 20 | ->setMethods(array('getName')) 21 | ->disableAutoload() 22 | ->getMock(); 23 | $bios->expects($this->once()) 24 | ->method('launch') 25 | ->with($operatingSys); 26 | $operatingSys 27 | ->expects($this->once()) 28 | ->method('getName') 29 | ->will($this->returnValue('Linux')); 30 | 31 | $facade = new Computer($bios, $operatingSys); 32 | return array(array($facade, $operatingSys)); 33 | } 34 | 35 | /** 36 | * @dataProvider getComputer 37 | */ 38 | public function testComputerOn(Computer $facade, $os) 39 | { 40 | // interface is simpler : 41 | $facade->turnOn(); 42 | // but I can access to lower component 43 | $this->assertEquals('Linux', $os->getName()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Structural/Facade/uml/Facade.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Structural\Facade\BiosInterface 5 | 6 | \DesignPatterns\Structural\Facade\BiosInterface 7 | \DesignPatterns\Structural\Facade\OsInterface 8 | \DesignPatterns\Structural\Facade\Facade 9 | 10 | 11 | 12 | 13 | 14 | \DesignPatterns\Structural\Facade\BiosInterface 15 | 16 | 17 | Fields 18 | Constants 19 | Constructors 20 | Methods 21 | 22 | private 23 | 24 | 25 | -------------------------------------------------------------------------------- /Structural/Facade/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Structural/Facade/uml/uml.png -------------------------------------------------------------------------------- /Structural/FluentInterface/README.md: -------------------------------------------------------------------------------- 1 | # Fluent Interface 2 | 3 | ## Propósito 4 | 5 | Escrever código que seja tão fácil de ler como sentenças em linguagem natural 6 | (como Português ou Inglês). 7 | 8 | ## Exemplos 9 | 10 | * QueryBuilder do Doctrine2 trabalha mais ou menos como essa classe complexa abaixo 11 | * PHPUnit usa Fluent Interfaces para construir objetos mock 12 | * Yii Framework: CDbCommand e CActiveRecord usam esse Padrão, também 13 | 14 | ## Diagrama UML 15 | 16 | ![Alt FluentInterface UML Diagram](uml/uml.png) 17 | -------------------------------------------------------------------------------- /Structural/FluentInterface/Sql.php: -------------------------------------------------------------------------------- 1 | fields = $fields; 35 | 36 | return $this; 37 | } 38 | 39 | /** 40 | * adds a FROM clause 41 | * 42 | * @param string $table 43 | * @param string $alias 44 | * 45 | * @return SQL 46 | */ 47 | public function from($table, $alias) 48 | { 49 | $this->from[] = $table . ' AS ' . $alias; 50 | 51 | return $this; 52 | } 53 | 54 | /** 55 | * adds a WHERE condition 56 | * 57 | * @param string $condition 58 | * 59 | * @return SQL 60 | */ 61 | public function where($condition) 62 | { 63 | $this->where[] = $condition; 64 | 65 | return $this; 66 | } 67 | 68 | /** 69 | * Gets the query, just an example of building a query, 70 | * no check on consistency 71 | * 72 | * @return string 73 | */ 74 | public function getQuery() 75 | { 76 | return 'SELECT ' . implode(',', $this->fields) 77 | . ' FROM ' . implode(',', $this->from) 78 | . ' WHERE ' . implode(' AND ', $this->where); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Structural/FluentInterface/Tests/FluentInterfaceTest.php: -------------------------------------------------------------------------------- 1 | select(array('foo', 'bar')) 17 | ->from('foobar', 'f') 18 | ->where('f.bar = ?') 19 | ->getQuery(); 20 | 21 | $this->assertEquals('SELECT foo,bar FROM foobar AS f WHERE f.bar = ?', $query); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Structural/FluentInterface/uml/FluentInterface.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Structural\FluentInterface\Sql 5 | 6 | \DesignPatterns\Structural\FluentInterface\Sql 7 | 8 | 9 | 10 | 11 | 12 | \DesignPatterns\Structural\FluentInterface\Sql 13 | 14 | 15 | Fields 16 | Constants 17 | Constructors 18 | Methods 19 | 20 | private 21 | 22 | 23 | -------------------------------------------------------------------------------- /Structural/FluentInterface/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Structural/FluentInterface/uml/uml.png -------------------------------------------------------------------------------- /Structural/Proxy/README.md: -------------------------------------------------------------------------------- 1 | # Proxy 2 | 3 | ## Propósito 4 | 5 | Fazer uma interface para qualquer coisa que seja custosa ou impossível de duplicar. 6 | 7 | ## Exemplos 8 | 9 | * Doctrine2 usa proxies para implementar mágica de framework -- por exemplo, 10 | instanciação preguiçosa (lazy initialization) -- enquanto o usuário continua a 11 | trabalhar com suas próprias classes e nunca usará ou nunca tocará nos proxies 12 | 13 | ## Diagrama UML 14 | 15 | ![Alt Proxy UML Diagram](uml/uml.png) 16 | -------------------------------------------------------------------------------- /Structural/Proxy/Record.php: -------------------------------------------------------------------------------- 1 | data = (array) $data; 21 | } 22 | 23 | /** 24 | * magic setter 25 | * 26 | * @param string $name 27 | * @param mixed $value 28 | * 29 | * @return void 30 | */ 31 | public function __set($name, $value) 32 | { 33 | $this->data[(string) $name] = $value; 34 | } 35 | 36 | /** 37 | * magic getter 38 | * 39 | * @param string $name 40 | * 41 | * @return mixed|null 42 | */ 43 | public function __get($name) 44 | { 45 | if (array_key_exists($name, $this->data)) { 46 | return $this->data[(string) $name]; 47 | } else { 48 | return null; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Structural/Proxy/RecordProxy.php: -------------------------------------------------------------------------------- 1 | isInitialized = true; 33 | $this->isDirty = true; 34 | } 35 | } 36 | 37 | /** 38 | * magic setter 39 | * 40 | * @param string $name 41 | * @param mixed $value 42 | * 43 | * @return void 44 | */ 45 | public function __set($name, $value) 46 | { 47 | $this->isDirty = true; 48 | parent::__set($name, $value); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Structural/Proxy/uml/Proxy.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Structural\Proxy\Record 5 | 6 | \DesignPatterns\Structural\Proxy\Record 7 | \DesignPatterns\Structural\Proxy\RecordProxy 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | \DesignPatterns\Structural\Proxy\Record 19 | 20 | 21 | Fields 22 | Constants 23 | Constructors 24 | Methods 25 | 26 | private 27 | 28 | 29 | -------------------------------------------------------------------------------- /Structural/Proxy/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Structural/Proxy/uml/uml.png -------------------------------------------------------------------------------- /Structural/README.md: -------------------------------------------------------------------------------- 1 | # Estrutural 2 | 3 | Em Engenharia de Software, Padrões de Projeto Estruturais são os que facilitam 4 | o design ao identificar uma maneira simples de realizar relacionamentos entre 5 | entidades 6 | 7 | * [Adapter](Adapter) [:notebook:](http://pt.wikipedia.org/wiki/Adapter) 8 | * [Bridge](Bridge) [:notebook:](http://pt.wikipedia.org/wiki/Bridge_%28padr%C3%A3o_de_projeto_de_software%29) 9 | * [Composite](Composite) [:notebook:](http://pt.wikipedia.org/wiki/Composite) 10 | * [DataMapper](DataMapper) [:notebook:](http://en.wikipedia.org/wiki/Data_mapper_pattern) 11 | * [Decorator](Decorator) [:notebook:](http://pt.wikipedia.org/wiki/Decorator) 12 | * [DependencyInjection](DependencyInjection) [:notebook:](http://en.wikipedia.org/wiki/Dependency_injection) 13 | * [Facade](Facade) [:notebook:](http://pt.wikipedia.org/wiki/Fa%C3%A7ade) 14 | * [FluentInterface](FluentInterface) [:notebook:](http://en.wikipedia.org/wiki/Fluent_interface) 15 | * [Proxy](Proxy) [:notebook:](http://pt.wikipedia.org/wiki/Proxy_%28padr%C3%B5es_de_projeto%29) 16 | * [Registry](Registry) [:notebook:](http://en.wikipedia.org/wiki/Service_locator_pattern) 17 | -------------------------------------------------------------------------------- /Structural/Registry/README.md: -------------------------------------------------------------------------------- 1 | # Registry 2 | 3 | ## Propósito 4 | 5 | Implementar um armazenamento central para objetos frequentemente usados em toda 6 | a aplicação. É tipicamente implementado usando uma classe abstrata com apenas 7 | métodos estáticos -- ou o Padrão Singleton. 8 | 9 | ## Exemplos 10 | 11 | * Zend Framework: `Zend_Registry` armazena o objeto de log da aplicação, front 12 | controller etc 13 | * Yii Framework: `CWebApplication` armazena todos os componentes da aplicação, 14 | como `CWebUser`, `CUrlManager` etc 15 | 16 | ## Diagrama UML 17 | 18 | ![Alt Registry UML Diagram](uml/uml.png) 19 | -------------------------------------------------------------------------------- /Structural/Registry/Registry.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('StdClass', $logger); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Structural/Registry/uml/Registry.uml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP 4 | \DesignPatterns\Structural\Registry\Registry 5 | 6 | \DesignPatterns\Structural\Registry\Registry 7 | 8 | 9 | 10 | 11 | 12 | \DesignPatterns\Structural\Registry\Registry 13 | 14 | 15 | Fields 16 | Constants 17 | Constructors 18 | Methods 19 | 20 | private 21 | 22 | 23 | -------------------------------------------------------------------------------- /Structural/Registry/uml/uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/Structural/Registry/uml/uml.png -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "domnikl/design-patterns-php", 3 | "description": "Sample code for several design patterns in PHP", 4 | "authors": [ 5 | { 6 | "name": "Dominik Liebler", 7 | "email": "liebler.dominik@googlemail.com" 8 | } 9 | ], 10 | "minimum-stability": "stable", 11 | "require-dev": { 12 | "phpunit/phpunit": "3.7.*", 13 | "squizlabs/php_codesniffer": "1.5.*" 14 | }, 15 | "autoload": { 16 | "psr-4": { 17 | "DesignPatterns\\": "" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /composer.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webfatorial/PadroesDeProjetoPHP/29e0acbb384dba6415141d3ae0270a31fb527553/composer.phar -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Behavioral/*/Tests 7 | Creational/*/Tests 8 | More/*/Tests 9 | Structural/*/Tests 10 | 11 | 12 | 13 | 14 | ./vendor 15 | 16 | 17 | 18 | --------------------------------------------------------------------------------