diff --git a/Behavioral/Memento/Caretaker.php b/Behavioral/Memento/Caretaker.php new file mode 100644 index 0000000..340bb97 --- /dev/null +++ b/Behavioral/Memento/Caretaker.php @@ -0,0 +1,33 @@ +setState("State1"); + //Setting state to State2 + $originator->setState("State2"); + //Saving State2 to Memento + $savedStates[] = $originator->saveToMemento(); + //Setting state to State3 + $originator->setState("State3"); + + // We can request multiple mementos, and choose which one to roll back to. + // Saving State3 to Memento + $savedStates[] = $originator->saveToMemento(); + //Setting state to State4 + $originator->setState("State4"); + + $originator->restoreFromMemento($savedStates[1]); + //State after restoring from Memento: State3 + } +} diff --git a/Behavioral/Memento/Memento.php b/Behavioral/Memento/Memento.php new file mode 100644 index 0000000..4dd2fc8 --- /dev/null +++ b/Behavioral/Memento/Memento.php @@ -0,0 +1,25 @@ +state = $stateToSave; + } + + /** + * @return mixed + */ + public function getState() + { + return $this->state; + } +} diff --git a/Behavioral/Memento/MementoTest.php b/Behavioral/Memento/MementoTest.php new file mode 100644 index 0000000..4d25d4d --- /dev/null +++ b/Behavioral/Memento/MementoTest.php @@ -0,0 +1,67 @@ +setState("State1"); + + $this->assertAttributeEquals("State1", "state", $originator); + + $originator->setState("State2"); + + $this->assertAttributeEquals("State2", "state", $originator); + + $savedState = $originator->saveToMemento(); + + $this->assertAttributeEquals("State2", "state", $savedState); + + $originator->setState("State3"); + + $this->assertAttributeEquals("State3", "state", $originator); + + $originator->restoreFromMemento($savedState); + + $this->assertAttributeEquals("State2", "state", $originator); + } + + public function testObjectState() + { + $originator = new Originator(); + + $foo = new \stdClass(); + $foo->data = "foo"; + + $originator->setState($foo); + + $this->assertAttributeEquals($foo, "state", $originator); + + $savedState = $originator->saveToMemento(); + + $this->assertAttributeEquals($foo, "state", $savedState); + + $bar = new \stdClass(); + $bar->data = "bar"; + + $originator->setState($bar); + + $this->assertAttributeEquals($bar, "state", $originator); + + $originator->restoreFromMemento($savedState); + + $this->assertAttributeEquals($foo, "state", $originator); + + $foo->data = null; + + $this->assertAttributeNotEquals($foo, "state", $savedState); + + $this->assertAttributeNotEquals($foo, "state", $originator); + } +} diff --git a/Behavioral/Memento/Originator.php b/Behavioral/Memento/Originator.php new file mode 100644 index 0000000..fec4e45 --- /dev/null +++ b/Behavioral/Memento/Originator.php @@ -0,0 +1,35 @@ +state = $state; + } + + /** + * @return Memento + */ + public function saveToMemento() + { + $state = is_object($this->state) ? clone $this->state : $this->state; + + return new Memento($state); + } + + public function restoreFromMemento(Memento $memento) + { + $this->state = $memento->getState(); + } +} diff --git a/Behavioral/Memento/README.md b/Behavioral/Memento/README.md new file mode 100644 index 0000000..83ca2c0 --- /dev/null +++ b/Behavioral/Memento/README.md @@ -0,0 +1,18 @@ +# Memento + +## Purpose + +Provide the ability to restore an object to its previous state (undo via rollback). + +The memento pattern is implemented with three objects: the originator, a caretaker and a memento. +The originator is some object that has an internal state. +The caretaker is going to do something to the originator, but wants to be able to undo the change. +The caretaker first asks the originator for a memento object. Then it does whatever operation (or sequence of operations) it was going to do. +To roll back to the state before the operations, it returns the memento object to the originator. +The memento object itself is an opaque object (one which the caretaker cannot, or should not, change). +When using this pattern, care should be taken if the originator may change other objects or resources - the memento pattern operates on a single object. + +## Examples + +* The seed of a pseudorandom number generator +* The state in a finite state machine diff --git a/More/ServiceLocator/ServiceLocatorTest.php b/More/ServiceLocator/ServiceLocatorTest.php index e50a436..5e20cc7 100644 --- a/More/ServiceLocator/ServiceLocatorTest.php +++ b/More/ServiceLocator/ServiceLocatorTest.php @@ -26,22 +26,15 @@ class ServiceLocatorTest extends TestCase public function setUp() { - $this->serviceLocator = new ServiceLocator(); - - $this->logService = new LogService(); + $this->serviceLocator = new ServiceLocator(); + $this->logService = new LogService(); $this->databaseService = new DatabaseService(); } public function testHasServices() { - $this->serviceLocator->add( - 'DesignPatterns\More\ServiceLocator\LogServiceInterface', - $this->logService - ); - $this->serviceLocator->add( - 'DesignPatterns\More\ServiceLocator\DatabaseServiceInterface', - $this->databaseService - ); + $this->serviceLocator->add('DesignPatterns\More\ServiceLocator\LogServiceInterface', $this->logService); + $this->serviceLocator->add('DesignPatterns\More\ServiceLocator\DatabaseServiceInterface', $this->databaseService); $this->assertTrue($this->serviceLocator->has('DesignPatterns\More\ServiceLocator\LogServiceInterface')); $this->assertTrue($this->serviceLocator->has('DesignPatterns\More\ServiceLocator\DatabaseServiceInterface')); diff --git a/README.md b/README.md index 4313611..57f2cb6 100644 --- a/README.md +++ b/README.md @@ -14,17 +14,18 @@ The patterns can be structured in roughly three different categories. Please cli * [AbstractFactory](Creational/AbstractFactory) [:notebook:](http://en.wikipedia.org/wiki/Abstract_factory_pattern) * [Builder](Creational/Builder) [:notebook:](http://en.wikipedia.org/wiki/Builder_pattern) -* [SimpleFactory](Creational/SimpleFactory) * [FactoryMethod](Creational/FactoryMethod) [:notebook:](http://en.wikipedia.org/wiki/Factory_method_pattern) -* [StaticFactory](Creational/StaticFactory) -* [Prototype](Creational/Prototype) [:notebook:](http://en.wikipedia.org/wiki/Prototype_pattern) -* [Pool](Creational/Pool) [:notebook:](http://en.wikipedia.org/wiki/Object_pool_pattern) -* [Singleton](Creational/Singleton) [:notebook:](http://en.wikipedia.org/wiki/Singleton_pattern) (is considered an anti-pattern! :no_entry:) * [Multiton](Creational/Multiton) (is considered an anti-pattern! :no_entry:) +* [Pool](Creational/Pool) [:notebook:](http://en.wikipedia.org/wiki/Object_pool_pattern) +* [Prototype](Creational/Prototype) [:notebook:](http://en.wikipedia.org/wiki/Prototype_pattern) +* [SimpleFactory](Creational/SimpleFactory) +* [Singleton](Creational/Singleton) [:notebook:](http://en.wikipedia.org/wiki/Singleton_pattern) (is considered an anti-pattern! :no_entry:) +* [StaticFactory](Creational/StaticFactory) ### [Structural](Structural) * [Adapter](Structural/Adapter) [:notebook:](http://en.wikipedia.org/wiki/Adapter_pattern) +* [Bridge](Structural/Bridge) [:notebook:](http://en.wikipedia.org/wiki/Bridge_pattern) * [Composite](Structural/Composite) [:notebook:](http://en.wikipedia.org/wiki/Composite_pattern) * [DataMapper](Structural/DataMapper) [:notebook:](http://en.wikipedia.org/wiki/Data_mapper_pattern) * [Decorator](Structural/Decorator) [:notebook:](http://en.wikipedia.org/wiki/Decorator_pattern) @@ -40,6 +41,7 @@ The patterns can be structured in roughly three different categories. Please cli * [Command](Behavioral/Command) [:notebook:](http://en.wikipedia.org/wiki/Command_pattern) * [Iterator](Behavioral/Iterator) [:notebook:](http://en.wikipedia.org/wiki/Iterator_pattern) * [Mediator](Behavioral/Mediator) [:notebook:](http://en.wikipedia.org/wiki/Mediator_pattern) +* [Memento](Memento) [:notebook:](http://en.wikipedia.org/wiki/Memento_pattern) * [NullObject](Behavioral/NullObject) [:notebook:](http://en.wikipedia.org/wiki/Null_Object_pattern) * [Observer](Behavioral/Observer) [:notebook:](http://en.wikipedia.org/wiki/Observer_pattern) * [Specification](Behavioral/Specification) [:notebook:](http://en.wikipedia.org/wiki/Specification_pattern) @@ -61,7 +63,7 @@ To establish a consistent code quality, please check your code using [PHP_CodeSn (The MIT License) -Copyright (c) 2013 Dominik Liebler +Copyright (c) 2014 Dominik Liebler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/Structural/Bridge/Assemble.php b/Structural/Bridge/Assemble.php new file mode 100644 index 0000000..2b60889 --- /dev/null +++ b/Structural/Bridge/Assemble.php @@ -0,0 +1,12 @@ +expectOutputString('Car Produced Assembled'); + $vehicle->manufacture(); + } + + public function testMotorcycle() + { + $vehicle = new Motorcycle(new Produce(), new Assemble()); + $this->expectOutputString('Motorcycle Produced Assembled'); + $vehicle->manufacture(); + } +} diff --git a/Structural/Bridge/Car.php b/Structural/Bridge/Car.php new file mode 100644 index 0000000..2754199 --- /dev/null +++ b/Structural/Bridge/Car.php @@ -0,0 +1,22 @@ +workShop1->work(); + $this->workShop2->work(); + } +} diff --git a/Structural/Bridge/Motorcycle.php b/Structural/Bridge/Motorcycle.php new file mode 100644 index 0000000..b021ce6 --- /dev/null +++ b/Structural/Bridge/Motorcycle.php @@ -0,0 +1,22 @@ +workShop1->work(); + $this->workShop2->work(); + } +} diff --git a/Structural/Bridge/Produce.php b/Structural/Bridge/Produce.php new file mode 100644 index 0000000..b2b0505 --- /dev/null +++ b/Structural/Bridge/Produce.php @@ -0,0 +1,15 @@ +workShop1 = $workShop1; + $this->workShop2 = $workShop2; + } + + public function manufacture() + { + } +} diff --git a/Structural/Bridge/Workshop.php b/Structural/Bridge/Workshop.php new file mode 100644 index 0000000..dc62886 --- /dev/null +++ b/Structural/Bridge/Workshop.php @@ -0,0 +1,12 @@ +