初识设计模式——备忘录模式(Memento Pattern)

cuixiaogang

备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏对象封装性的前提下,捕获并保存一个对象的内部状态,以便后续可以将该对象恢复到之前保存的状态。

备忘录模式的构成

  • 发起人(Originator):创建包含当前内部状态的备忘录对象,也能使用备忘录对象恢复其内部状态。
  • 备忘录(Memento):用于存储发起人的内部状态,且除发起人外,其他对象不能访问该状态。
  • 管理者(Caretaker):负责保存备忘录对象,但不检查或修改备忘录的内容。

备忘录模式结构图

案例

场景

在一个简单的在线表单编辑场景中,用户在填写表单时可能会误操作或者想要回到之前的填写状态,这时可以使用备忘录模式来实现表单状态的保存和恢复。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?php
// 备忘录类
class FormMemento {
private $formData;

public function __construct($formData) {
$this->formData = $formData;
}

public function getFormData() {
return $this->formData;
}
}

// 发起人类
class FormOriginator {
private $formData;

public function setFormData($formData) {
$this->formData = $formData;
}

public function getFormData() {
return $this->formData;
}

public function saveToMemento() {
return new FormMemento($this->formData);
}

public function restoreFromMemento(FormMemento $memento) {
$this->formData = $memento->getFormData();
}
}

// 管理者类
class FormCaretaker {
private $mementos = [];

public function addMemento(FormMemento $memento) {
$this->mementos[] = $memento;
}

public function getMemento($index) {
return isset($this->mementos[$index]) ? $this->mementos[$index] : null;
}
}

// 使用示例
$formOriginator = new FormOriginator();
$formCaretaker = new FormCaretaker();

// 第一次填写表单
$formData1 = [
'name' => 'John Doe',
'email' => 'johndoe@example.com'
];
$formOriginator->setFormData($formData1);
// 保存当前状态
$formCaretaker->addMemento($formOriginator->saveToMemento());

// 第二次填写表单
$formData2 = [
'name' => 'Jane Smith',
'email' => 'janesmith@example.com'
];
$formOriginator->setFormData($formData2);
// 保存当前状态
$formCaretaker->addMemento($formOriginator->saveToMemento());

// 恢复到第一次填写的状态
$firstMemento = $formCaretaker->getMemento(0);
if ($firstMemento) {
$formOriginator->restoreFromMemento($firstMemento);
print_r($formOriginator->getFormData());
}

代码解释

  • FormMemento 类作为备忘录,用于存储表单数据;
  • FormOriginator 类是发起人,负责设置和获取表单数据,同时可以保存和恢复表单状态;
  • FormCaretaker 类是管理者,负责管理备忘录对象。

UML类图

UML类图

备忘录模式的适用场景

  • 撤销操作:在很多软件中,用户执行的操作需要支持撤销功能,这时可以使用备忘录模式来保存操作前的状态,以便撤销操作时恢复。
  • 历史记录:需要记录对象状态历史,以便后续查看或恢复到某个历史状态的场景。
  • 事务管理:在数据库事务管理中,当事务执行失败时,需要回滚到事务开始前的状态,备忘录模式可用于保存事务开始前的状态。

备忘录模式的优缺点

优点

  • 封装性良好:备忘录模式将对象状态的保存和恢复细节封装起来,发起人的状态信息不会被外部对象随意访问和修改。
  • 简化发起人职责:发起人不需要自行管理状态的保存和恢复,将这些操作交给管理者和备忘录对象,降低了发起人的复杂度。
  • 支持撤销和恢复:方便实现对象状态的撤销和恢复操作,提升用户体验。

缺点

  • 资源消耗大:如果需要保存的状态信息较多,或者频繁保存状态,会占用大量的内存空间。
  • 维护成本高:当发起人对象的状态发生变化时,可能需要修改备忘录类和管理者类,增加了维护的难度。