目录
备忘录模式(Memento Pattern)
备忘录模式(Memento Pattern)又叫快照模式。通过在不破坏封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,从而在需要时能够将对象恢复到之前的状态。
备忘录模式的核心角色:
- 发起人(Originator):负责创建备忘录对象,并可以使用备忘录对象恢复自身状态。
- 备忘录(Memento):用于存储发起人的内部状态,是 Originator 的快照。
- 管理者(Caretaker):负责保存和恢复备忘录。
优缺点
(1)优点:
- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
- 实现了信息的封装,使得用户不需要关心状态的保存细节,能够在不破坏封装的前提下实现状态的保存和恢复。
(2)缺点:
- 消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
- 并发安全。在多线程场景,实现备忘录模式时,要注意在保证状态的不变性,否则可能会有并发安全问题。
使用场景
- 事务回滚。事务回滚的一种常见实现方法是 undo log,其本质上用的就是备忘录模式。
- 系统快照(Snapshot)。多版本控制的用法,保存某一时刻的系统状态快照,以便在将来能够恢复。
-
撤销功能。比如 Microsoft Offices 这类的文档编辑软件的撤销功能。
注意事项
- 为了符合迪米特原则,还要增加一个管理备忘录的类。
- 为了节约内存,可使用原型模式+备忘录模式。
- 在实现 Undo/Redo 操作时,你通常需要同时使用备忘录模式与命令模式
- 另外,当你需要遍历备忘录对象中的成员时,通常会使用迭代器模式,以防破坏对象的封装。
代码实现
package main
import "fmt"
// 文本编辑器应用程序,用户可以输入和编辑文本。希望能够实现撤销功能,即用户可以撤销之前的操作,恢复到之前的编辑状态。
// 备忘录对象
type Memento struct {
state string
}
func (m *Memento) GetState() string {
return m.state
}
// 发起人对象
type Originator struct {
state string
}
func (o *Originator) SetState(state string) {
o.state = state
}
func (o *Originator) CreateMemento() *Memento {
return &Memento{state: o.state}
}
func (o *Originator) RestoreMemento(memento *Memento) {
o.state = memento.GetState()
}
// 管理者对象
type Caretaker struct {
memento *Memento
}
func (c *Caretaker) SaveMemento(memento *Memento) {
c.memento = memento
}
func (c *Caretaker) GetMemento() *Memento {
return c.memento
}
// 客户端代码
func main() {
originator := &Originator{}
caretaker := &Caretaker{}
originator.SetState("State 1")
fmt.Println("当前状态:", originator.state)
caretaker.SaveMemento(originator.CreateMemento())
originator.SetState("State 2")
fmt.Println("当前状态:", originator.state)
originator.RestoreMemento(caretaker.GetMemento())
fmt.Println("恢复后的状态:", originator.state)
}