In the application design process, some specific actions need to be able to support undo (undo), such as a recently written file management system. Some basic operations of the file, such as rename, copy, cut, etc., need to support undo, redo operations to provide a better user experience. As is known to all, undo, redo operation requires two mode support: Memo mode (Memento) Save object Operation data State, Command mode (commands) encapsulate user request. The combination can provide good undo and redo operations. Command mode can refer to the previous article click the Open link. The following is mainly about the implementation of the memorandum pattern, if there are errors, do not enlighten.
The memo pattern consists of 3 participants:
A. Memo object that holds status information (Memento)
B. Source generator (originator) that generates status information
C. Manager of the Memo object (caretaker)
The source generator provides two external interfaces:
Create_memento (); Save Object state Information Create a memo return Set_memento (Memento $mem); Get status information based on incoming memo, restore status
a Memo object provides two interfaces:
Set_state (state $state); Device Memo Current status get_state (); Get Memo Current status
Memo Object implementations:
Class Memento { private $state; Public Function get_state () { return $this->state; } Public Function set_state (state $state) { $this->state = Clone $state; } }
The Set_state interface guarantees the uniqueness of the parameter type with the state parameter hint. It is important to note that the PHP default object assignment does not execute the copy constructor as C + +, PHP is based on the Reference object counter, the object assignment default counter plus one. Here we use the clone operation provided by PHP to ensure that we get a completely new object.
Source Generator Implementation:
Class originator{ private $state; function _construct () { $this->state = new State (); $this->state->set (' action ', ' create originator '); } function Do_action1 () { $this->state->set (' action ', ' do_action 1 '); } function Do_action2 () { $this->state->set (' action ', ' Do_action 2 '); } function Create_memento () { $mem = new Memento (); $men->set_state ($this->state); return $mem; } function Set_memento (Memento $mem) { $this->state = $mem->get_state (); } function dump () { echo $this->state->get (' action '). "\ n"; } }
Status information object:
Class state{ Private $values = Array (); Public function set ($key, $value) { $this->values[$key] = $value; } Public function Get ($key) { if (isset ($this->values[$key]) { return $this->values[$key]; } return null; } }
Finally, a simple implementation of the memo manager:
Class caretaker{private $command; function __construct ($cmd = "Originator1") {$this->command = $cmd; } Private Function Do_execute () {switch ($this->command) {case ' Originat Or1 ': {$action = new originator (); $mem 1 = $action->create_memento (); $action->dump (); $action->do_action1 (); $mem 2 = $action->create_memento (); $action->dump (); $action->do_action2 (); $mem 3 = $action->create_memento (); $action->dump (); State recovery $action->set_memento ($mem 2); $action->dump (); $action->set_memento ($mem 1); $action->dump (); } } } }
Here are a few places to improve, first, the manager should provide a queue to manage a series of Memo objects. Second, the client requests the command to distribute the request with a large switch-case rather than using the command pattern to encapsulate the requests as objects, resulting in class structure confusion. The next article will implement a full version of the Undo-redo operation.
The end.
Brief analysis of Memo mode