diff --git a/Behavioral/Memento/Caretaker.php b/Behavioral/Memento/Caretaker.php
deleted file mode 100644
index d80454a..0000000
--- a/Behavioral/Memento/Caretaker.php
+++ /dev/null
@@ -1,49 +0,0 @@
-history[$id];
- }
-
- /**
- * @param Memento $state
- */
- public function saveToHistory(Memento $state)
- {
- $this->history[] = $state;
- }
-
- public function runCustomLogic()
- {
- $originator = new Originator();
-
- //Setting state to State1
- $originator->setState('State1');
- //Setting state to State2
- $originator->setState('State2');
- //Saving State2 to Memento
- $this->saveToHistory($originator->getStateAsMemento());
- //Setting state to State3
- $originator->setState('State3');
-
- // We can request multiple mementos, and choose which one to roll back to.
- // Saving State3 to Memento
- $this->saveToHistory($originator->getStateAsMemento());
- //Setting state to State4
- $originator->setState('State4');
-
- $originator->restoreFromMemento($this->getFromHistory(1));
- //State after restoring from Memento: State3
-
- return $originator->getStateAsMemento()->getState();
- }
-}
diff --git a/Behavioral/Memento/Memento.php b/Behavioral/Memento/Memento.php
index 4dd2fc8..f75fcc9 100644
--- a/Behavioral/Memento/Memento.php
+++ b/Behavioral/Memento/Memento.php
@@ -4,19 +4,21 @@ namespace DesignPatterns\Behavioral\Memento;
class Memento
{
- /* @var mixed */
+ /**
+ * @var State
+ */
private $state;
/**
- * @param mixed $stateToSave
+ * @param State $stateToSave
*/
- public function __construct($stateToSave)
+ public function __construct(State $stateToSave)
{
$this->state = $stateToSave;
}
/**
- * @return mixed
+ * @return State
*/
public function getState()
{
diff --git a/Behavioral/Memento/Originator.php b/Behavioral/Memento/Originator.php
deleted file mode 100644
index 3acb0c1..0000000
--- a/Behavioral/Memento/Originator.php
+++ /dev/null
@@ -1,38 +0,0 @@
-state = $state;
- }
-
- /**
- * @return Memento
- */
- public function getStateAsMemento()
- {
- // you must save a separate copy in Memento
- $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.rst b/Behavioral/Memento/README.rst
index 911e30e..32ec703 100644
--- a/Behavioral/Memento/README.rst
+++ b/Behavioral/Memento/README.rst
@@ -6,8 +6,8 @@ Purpose
It provides the ability to restore an object to it's previous state (undo
via rollback) or to gain access to state of the object, without revealing
-it's implementation (i.e., the object is not required to have a functional
-for return the current state).
+it's implementation (i.e., the object is not required to have a function
+to return the current state).
The memento pattern is implemented with three objects: the Originator, a
Caretaker and a Memento.
@@ -66,9 +66,9 @@ Originator.php
:language: php
:linenos:
-Caretaker.php
+Ticket.php
-.. literalinclude:: Caretaker.php
+.. literalinclude:: Ticket.php
:language: php
:linenos:
diff --git a/Behavioral/Memento/State.php b/Behavioral/Memento/State.php
new file mode 100644
index 0000000..6cb5dd1
--- /dev/null
+++ b/Behavioral/Memento/State.php
@@ -0,0 +1,48 @@
+state = $state;
+ }
+
+ private static function ensureIsValidState(string $state)
+ {
+ if (!in_array($state, self::$validStates)) {
+ throw new \InvalidArgumentException('Invalid state given');
+ }
+ }
+
+ public function __toString(): string
+ {
+ return $this->state;
+ }
+}
diff --git a/Behavioral/Memento/Tests/MementoTest.php b/Behavioral/Memento/Tests/MementoTest.php
index 722dbfa..d4a44f3 100644
--- a/Behavioral/Memento/Tests/MementoTest.php
+++ b/Behavioral/Memento/Tests/MementoTest.php
@@ -2,161 +2,30 @@
namespace DesignPatterns\Behavioral\Memento\Tests;
-use DesignPatterns\Behavioral\Memento\Caretaker;
-use DesignPatterns\Behavioral\Memento\Memento;
-use DesignPatterns\Behavioral\Memento\Originator;
+use DesignPatterns\Behavioral\Memento\State;
+use DesignPatterns\Behavioral\Memento\Ticket;
-/**
- * MementoTest tests the memento pattern.
- */
class MementoTest extends \PHPUnit_Framework_TestCase
{
- public function testUsageExample()
+ public function testOpenTicketAssignAndSetBackToOpen()
{
- $originator = new Originator();
- $caretaker = new Caretaker();
+ $ticket = new Ticket();
- $character = new \stdClass();
- // new object
- $character->name = 'Gandalf';
- // connect Originator to character object
- $originator->setState($character);
+ // open the ticket
+ $ticket->open();
+ $openedState = $ticket->getState();
+ $this->assertEquals(State::STATE_OPENED, (string) $ticket->getState());
- // work on the object
- $character->name = 'Gandalf the Grey';
- // still change something
- $character->race = 'Maia';
- // time to save state
- $snapshot = $originator->getStateAsMemento();
- // put state to log
- $caretaker->saveToHistory($snapshot);
+ $memento = $ticket->saveToMemento();
- // change something
- $character->name = 'Sauron';
- // and again
- $character->race = 'Ainur';
- // state inside the Originator was equally changed
- $this->assertAttributeEquals($character, 'state', $originator);
+ // assign the ticket
+ $ticket->assign();
+ $this->assertEquals(State::STATE_ASSIGNED, (string) $ticket->getState());
- // time to save another state
- $snapshot = $originator->getStateAsMemento();
- // put state to log
- $caretaker->saveToHistory($snapshot);
+ // no restore to the opened state, but verify that the state object has been cloned for the memento
+ $ticket->restoreFromMemento($memento);
- $rollback = $caretaker->getFromHistory(0);
- // return to first state
- $originator->restoreFromMemento($rollback);
- // use character from old state
- $character = $rollback->getState();
-
- // yes, that what we need
- $this->assertEquals('Gandalf the Grey', $character->name);
- // make new changes
- $character->name = 'Gandalf the White';
-
- // and Originator linked to actual object again
- $this->assertAttributeEquals($character, 'state', $originator);
- }
-
- public function testStringState()
- {
- $originator = new Originator();
- $originator->setState('State1');
-
- $this->assertAttributeEquals('State1', 'state', $originator);
-
- $originator->setState('State2');
- $this->assertAttributeEquals('State2', 'state', $originator);
-
- $snapshot = $originator->getStateAsMemento();
- $this->assertAttributeEquals('State2', 'state', $snapshot);
-
- $originator->setState('State3');
- $this->assertAttributeEquals('State3', 'state', $originator);
-
- $originator->restoreFromMemento($snapshot);
- $this->assertAttributeEquals('State2', 'state', $originator);
- }
-
- public function testSnapshotIsClone()
- {
- $originator = new Originator();
- $object = new \stdClass();
-
- $originator->setState($object);
- $snapshot = $originator->getStateAsMemento();
- $object->new_property = 1;
-
- $this->assertAttributeEquals($object, 'state', $originator);
- $this->assertAttributeNotEquals($object, 'state', $snapshot);
-
- $originator->restoreFromMemento($snapshot);
- $this->assertAttributeNotEquals($object, 'state', $originator);
- }
-
- public function testCanChangeActualState()
- {
- $originator = new Originator();
- $first_state = new \stdClass();
-
- $originator->setState($first_state);
- $snapshot = $originator->getStateAsMemento();
- $second_state = $snapshot->getState();
-
- // still actual
- $first_state->first_property = 1;
- // just history
- $second_state->second_property = 2;
- $this->assertAttributeEquals($first_state, 'state', $originator);
- $this->assertAttributeNotEquals($second_state, 'state', $originator);
-
- $originator->restoreFromMemento($snapshot);
- // now it lost state
- $first_state->first_property = 11;
- // must be actual
- $second_state->second_property = 22;
- $this->assertAttributeEquals($second_state, 'state', $originator);
- $this->assertAttributeNotEquals($first_state, 'state', $originator);
- }
-
- public function testStateWithDifferentObjects()
- {
- $originator = new Originator();
-
- $first = new \stdClass();
- $first->data = 'foo';
-
- $originator->setState($first);
- $this->assertAttributeEquals($first, 'state', $originator);
-
- $first_snapshot = $originator->getStateAsMemento();
- $this->assertAttributeEquals($first, 'state', $first_snapshot);
-
- $second = new \stdClass();
- $second->data = 'bar';
- $originator->setState($second);
- $this->assertAttributeEquals($second, 'state', $originator);
-
- $originator->restoreFromMemento($first_snapshot);
- $this->assertAttributeEquals($first, 'state', $originator);
- }
-
- public function testCaretaker()
- {
- $caretaker = new Caretaker();
- $memento1 = new Memento('foo');
- $memento2 = new Memento('bar');
- $caretaker->saveToHistory($memento1);
- $caretaker->saveToHistory($memento2);
- $this->assertAttributeEquals(array($memento1, $memento2), 'history', $caretaker);
- $this->assertEquals($memento1, $caretaker->getFromHistory(0));
- $this->assertEquals($memento2, $caretaker->getFromHistory(1));
- }
-
- public function testCaretakerCustomLogic()
- {
- $caretaker = new Caretaker();
- $result = $caretaker->runCustomLogic();
- $this->assertEquals('State3', $result);
+ $this->assertEquals(State::STATE_OPENED, (string) $ticket->getState());
+ $this->assertNotSame($openedState, $ticket->getState());
}
}
diff --git a/Behavioral/Memento/Ticket.php b/Behavioral/Memento/Ticket.php
new file mode 100644
index 0000000..13f75e7
--- /dev/null
+++ b/Behavioral/Memento/Ticket.php
@@ -0,0 +1,49 @@
+currentState = new State(State::STATE_CREATED);
+ }
+
+ public function open()
+ {
+ $this->currentState = new State(State::STATE_OPENED);
+ }
+
+ public function assign()
+ {
+ $this->currentState = new State(State::STATE_ASSIGNED);
+ }
+
+ public function close()
+ {
+ $this->currentState = new State(State::STATE_CLOSED);
+ }
+
+ public function saveToMemento(): Memento
+ {
+ return new Memento(clone $this->currentState);
+ }
+
+ public function restoreFromMemento(Memento $memento)
+ {
+ $this->currentState = $memento->getState();
+ }
+
+ public function getState(): State
+ {
+ return $this->currentState;
+ }
+}
diff --git a/Behavioral/Memento/uml/Memento.uml b/Behavioral/Memento/uml/Memento.uml
new file mode 100644
index 0000000..194187a
--- /dev/null
+++ b/Behavioral/Memento/uml/Memento.uml
@@ -0,0 +1,21 @@
+
+
+ PHP
+ \DesignPatterns\Behavioral\Memento\Memento
+
+ \DesignPatterns\Behavioral\Memento\State
+ \DesignPatterns\Behavioral\Memento\Memento
+ \DesignPatterns\Behavioral\Memento\Ticket
+
+
+
+
+
+
+ Fields
+ Constants
+ Methods
+
+ private
+
+
diff --git a/Behavioral/Memento/uml/Momento.uml b/Behavioral/Memento/uml/Momento.uml
deleted file mode 100644
index c72667e..0000000
--- a/Behavioral/Memento/uml/Momento.uml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
- PHP
- \DesignPatterns\Behavioral\Memento\Caretaker
-
- \DesignPatterns\Behavioral\Memento\Caretaker
- \DesignPatterns\Behavioral\Memento\Originator
- \DesignPatterns\Behavioral\Memento\Memento
-
-
-
-
-
-
- Fields
- Constants
- Constructors
- Methods
-
- private
-
-
diff --git a/Behavioral/Memento/uml/uml.png b/Behavioral/Memento/uml/uml.png
index 0fde074..417b293 100644
Binary files a/Behavioral/Memento/uml/uml.png and b/Behavioral/Memento/uml/uml.png differ
diff --git a/Behavioral/Memento/uml/uml.svg b/Behavioral/Memento/uml/uml.svg
index 2cc47a8..aeb665a 100644
--- a/Behavioral/Memento/uml/uml.svg
+++ b/Behavioral/Memento/uml/uml.svg
@@ -1,310 +1,952 @@
-
+