[toc]
## 举个例子
> 用过锤子手机的闪念胶囊APP吗?
> 在你状态好, 有灵感的时候, 把想法记下来
> 等你有时间写作的时候, 即使不在状态, 依然"记得"那些好想法...
## 代码示例
```php
<?php
// 工程师
class Engineer {
private $name;
private $workItems;
public function __construct($name) {
$this->name = $name;
$this->workItems = [];
}
public function addWorkItem($item) {
array_push($this->workItems, $item);
}
public function forget() {
$this->workItems = [];
echo $this->name . "工作太忙了,都忘记要做什么了!";
}
public function writeTodoList() {
$todoList = new TodoList();
foreach ($this->workItems as $item) {
$todoList->writeWorkItem($item);
}
return $todoList;
}
public function retrospect($todoList) {
$this->workItems = $todoList->getWorkItems();
echo $this->name . "想起要做什么了!";
}
public function showWorkItem() {
if (count($this->workItems)) {
echo $this->name . "的工作项:" . PHP_EOL;
foreach ($this->workItems as $key => $value) {
echo strval($key + 1) . '-->' . $this->workItems[$key] . ';' . PHP_EOL;
}
} else {
echo $this->name . "暂无工作项!" . PHP_EOL;
}
}
}
// 工作项
class TodoList {
private $workItems;
public function __construct() {
$this->workItems = [];
}
public function writeWorkItem($item) {
array_push($this->workItems, $item);
}
public function getWorkItems() {
return $this->workItems;
}
}
// TodoList管理类
class TodoListCaretaker {
private $todoList;
public function __construct() {
$this->todoList = null;
}
public function setTodoList($todoList) {
$this->todoList = $todoList;
}
public function getTodoList() {
return $this->todoList;
}
}
// 测试代码
$tony = new Engineer("Tony");
$tony->addWorkItem("解决线上部分用户因昵称太长而无法显示全的问题");
$tony->addWorkItem("完成PDF的解析");
$tony->addWorkItem("在阅读器中显示PDF第一页的内容");
$tony->showWorkItem();
$caretaker = new TodoListCaretaker();
$caretaker->setTodoList($tony->writeTodoList());
echo PHP_EOL;
$tony->forget();
$tony->showWorkItem();
echo PHP_EOL;
$tony->retrospect($caretaker->getTodoList());
$tony->showWorkItem();
```
```
D:\soft\php72\php.exe D:\project\php_dp\index.php
Tony的工作项:
1-->解决线上部分用户因昵称太长而无法显示全的问题;
2-->完成PDF的解析;
3-->在阅读器中显示PDF第一页的内容;
Tony工作太忙了,都忘记要做什么了!Tony暂无工作项!
Tony想起要做什么了!Tony的工作项:
1-->解决线上部分用户因昵称太长而无法显示全的问题;
2-->完成PDF的解析;
3-->在阅读器中显示PDF第一页的内容;
Process finished with exit code 0
```
## 什么是备忘模式?
> 在不破坏内部结构的前提下捕获一个对象的内部状态,这样便可在以后将该对象恢复到原先保存的状态。
1. 备忘录模式的最大功能就是做备份,可以保存对象的一个状态作为备份,这样便可让对象在将来的某一时刻恢复到之前保存的状态。
2. 如同游戏中“死”了的英雄可以满血复活一样
3. 再比如很多电器(如电视、冰箱)都有恢复出厂设置的功能
4. 人生没有彩排,但程序却可以让你无数次回放!
![](https://box.kancloud.cn/851562a5512f4e962f58327f13c3a236_489x308.png)
## 设计要点
1. **发起人(Originator)**: 需要进行备份的对象。
1. **备忘录(Memento)**: 备份的状态,即一个备份的存档。
1. **备忘录管理者(Caretaker)**: 备份存档的管理者,由它负责与发起人的交互。
## 优缺点
**备忘录模式的优点**:
1. 给用户提供了一种可以恢复状态的机制,使得用户能够比较方便地回到某个历史的状态。
1. 实现了信息的封装,用户不需要关心状态的保存细节。
**备忘录模式的缺点**:
1. 如果类的成员变量过多,势必会占用比较大的资源,
2. 每一次保存都会消耗一定的内存,此时可以限制保存的最大次数。
## 应用场景
1. 需要保存/恢复对象的状态或数据,如游戏的存档、虚拟机的快照。
1. 需要实现撤销、恢复功能的场景,如 Word 中的 Ctrl+Z、Ctrl+Y 功能,DOS 命令行或 Linux 终端的命令记忆功能。
1. 提供一个可回滚的操作,如数据库的事务管理。