设计模式笔记 - 备忘录模式

151 阅读2分钟

备忘录模式是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。


解决什么问题?

  • 当你需要创建对象状态快照来恢复其之前的状态时, 可以使用备忘录模式。
  • 当直接访问对象的成员变量、 获取器或设置器将导致封装被突破时, 可以使用该模式。

优势:

  • 你可以在不破坏对象封装情况的前提下创建对象状态快照。
  • 你可以通过让负责人维护原发器状态历史记录来简化原发器代码。

劣势:

  • 如果客户端过于频繁地创建备忘录, 程序将消耗大量内存。
  • 负责人必须完整跟踪原发器的生命周期, 这样才能销毁弃用的备忘录。
  • 绝大部分动态编程语言 (例如 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
}

参考