共计 3363 个字符,预计需要花费 9 分钟才能阅读完成。
简介
容许在不裸露对象实现细节的状况下保留和复原对象之前的状态,该状态保留在对象之外,这样就能够不毁坏原有对象的封装性了。
角色
-
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: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVI
Caretaker: Saving Originator's state...
Originator: I'm doing something important.
Originator: and my state has changed to: YrymDJvtFqlwGpMuCNXadsQonIVPzR
Caretaker: Saving Originator's state...
Originator: I'm doing something important.
Originator: and my state has changed to: pOuLBUelsmFRkKrbhAGfqzTtQXjnNH
Caretaker: 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: YrymDJvtFqlwGpMuCNXadsQonIVPzR
Client: Once more!
Caretaker: Restoring state to: 2023-06-28 01:51:01 / (uDdcJyRkb...)
Originator: My state has changed to: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVI
本文由 mdnice 多平台公布
正文完