简介
容许在不裸露对象实现细节的状况下保留和复原对象之前的状态,该状态保留在对象之外,这样就能够不毁坏原有对象的封装性了。
角色
Originator 原发器
即须要被保留状态的类
形象 Memento 备忘录类
定义备忘录根本接口
能够看做成是快照 Snapshot
具体 Memento 备忘录类
实现接口
Caretaker 负责人
即连贯Originator和Memento的类,保护一个Memento队列,通过操作队列实现undo redo的操作
类图
图中,ConcreteOriginator通过save办法,生成一个Memento,Caretaker 的history属性保留这些Memento,实现undo操作。
代码
class Originator{ private $state; public function __construct(string $state) { $this->state = $state; echo "Originator: My initial state is: {$this->state}\n"; } public function doSomething(): void { echo "Originator: I'm doing something important.\n"; $this->state = $this->generateRandomString(30); echo "Originator: and my state has changed to: {$this->state}\n"; } private function generateRandomString(int $length = 10): string { return substr( str_shuffle( str_repeat( $x = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)) ) ), 1, $length ); } public function save(): Memento { return new ConcreteMemento($this->state); } public function restore(Memento $memento): void { $this->state = $memento->getState(); echo "Originator: My state has changed to: {$this->state}\n"; }}interface Memento{ public function getName(): string; public function getDate(): string;}class ConcreteMemento implements Memento{ private $state; private $date; public function __construct(string $state) { $this->state = $state; $this->date = date('Y-m-d H:i:s'); } public function getState(): string { return $this->state; } public function getName(): string { return $this->date . " / (" . substr($this->state, 0, 9) . "...)"; } public function getDate(): string { return $this->date; }}class Caretaker{ private $mementos = []; private $originator; public function __construct(Originator $originator) { $this->originator = $originator; } public function backup(): void { echo "\nCaretaker: Saving Originator's state...\n"; $this->mementos[] = $this->originator->save(); } public function undo(): void { if (!count($this->mementos)) { return; } $memento = array_pop($this->mementos); echo "Caretaker: Restoring state to: " . $memento->getName() . "\n"; try { $this->originator->restore($memento); } catch (\Exception $e) { $this->undo(); } } public function showHistory(): void { echo "Caretaker: Here's the list of mementos:\n"; foreach ($this->mementos as $memento) { echo $memento->getName() . "\n"; } }}$originator = new Originator("Super-duper-super-puper-super.");$caretaker = new Caretaker($originator);$caretaker->backup();$originator->doSomething();$caretaker->backup();$originator->doSomething();$caretaker->backup();$originator->doSomething();echo "\n";$caretaker->showHistory();echo "\nClient: Now, let's rollback!\n\n";$caretaker->undo();echo "\nClient: Once more!\n\n";$caretaker->undo();
output:
Originator: My initial state is: Super-duper-super-puper-super.Caretaker: Saving Originator's state...Originator: I'm doing something important.Originator: and my state has changed to: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVICaretaker: Saving Originator's state...Originator: I'm doing something important.Originator: and my state has changed to: YrymDJvtFqlwGpMuCNXadsQonIVPzRCaretaker: Saving Originator's state...Originator: I'm doing something important.Originator: and my state has changed to: pOuLBUelsmFRkKrbhAGfqzTtQXjnNHCaretaker: Here's the list of mementos:2023-06-28 01:51:01 / (Super-dup...)2023-06-28 01:51:01 / (uDdcJyRkb...)2023-06-28 01:51:01 / (YrymDJvtF...)Client: Now, let's rollback!Caretaker: Restoring state to: 2023-06-28 01:51:01 / (YrymDJvtF...)Originator: My state has changed to: YrymDJvtFqlwGpMuCNXadsQonIVPzRClient: Once more!Caretaker: Restoring state to: 2023-06-28 01:51:01 / (uDdcJyRkb...)Originator: My state has changed to: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVI
本文由mdnice多平台公布