备忘录模式是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。
解决什么问题?
- 当你需要创建对象状态快照来恢复其之前的状态时, 可以使用备忘录模式。
- 当直接访问对象的成员变量、 获取器或设置器将导致封装被突破时, 可以使用该模式。
优势:
- 你可以在不破坏对象封装情况的前提下创建对象状态快照。
- 你可以通过让负责人维护原发器状态历史记录来简化原发器代码。
劣势:
- 如果客户端过于频繁地创建备忘录, 程序将消耗大量内存。
- 负责人必须完整跟踪原发器的生命周期, 这样才能销毁弃用的备忘录。
- 绝大部分动态编程语言 (例如 PHP、 Python 和 JavaScript) 不能确保备忘录中的状态不被修改。
实现步骤:
- 定义
原发器接口 - 定义
备忘录接口 - 定义
责任人类,主要作用是保存备忘录类 - 定义
备忘录类,实现备忘录接口,关联原发器类,修改原发器引用对象的状态 - 定义
原发器类,实现原发器接口,关联责任人类,将新建的备忘录对象放入责任人对象中
下面是实现代码:
package main
import "fmt"
type originator interface {
save()
}
type memento interface {
restore()
}
type caretaker struct {
history []memento
}
func newCareTaker() *caretaker {
return &caretaker{
history: make([]memento, 0),
}
}
func (c *caretaker) undo() {
l := len(c.history)
if l <= 0 {
fmt.Println("no more history")
return
}
m := c.history[l-1]
c.history = c.history[:l-1]
m.restore()
}
func (c *caretaker) push(m memento) {
c.history = append(c.history, m)
}
type editorMemento struct {
editor originator
state int
}
func (e *editorMemento) restore() {
et, ok := e.editor.(*editor)
if !ok {
return
}
et.setState(e.state)
}
type editor struct {
state int
taker *caretaker
}
func newEditor(taker *caretaker) *editor {
return &editor{
state: 0,
taker: taker,
}
}
func (e *editor) setState(s int) {
e.state = s
}
func (e *editor) save() {
m := &editorMemento{
editor: e,
state: e.state,
}
e.taker.push(m)
}
func (e *editor) dump() {
fmt.Println(e.state)
}
func main() {
taker := newCareTaker()
e := newEditor(taker)
e.setState(1)
e.save()
e.setState(2)
e.dump() // 2
taker.undo()
e.dump() // 1
taker.undo() // no more history
e.dump() // 1
}