备忘录模式(Memento Pattern)

未匹配的标注

备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装性的前提下保存和恢复对象的内部状态。该模式涉及三个主要角色:Originator(发起人)、Memento(备忘录)和Caretaker(负责人)。Originator 是拥有内部状态的对象,Memento 是 Originator 的快照,Caretaker 负责备份和恢复 Memento。

备忘录模式在实现撤销操作和历史记录等功能时非常有用。

下面是一个使用 Go 语言实现备忘录模式的示例。在本例中,我们将实现一个简单的文本编辑器,该编辑器允许用户撤销和重做操作。

首先,我们定义 Originator 接口,该接口定义了保存当前状态和从备忘录中恢复状态的方法:

type Originator interface {
    Save() Memento
    Restore(m Memento)
}

接下来,我们定义 Memento 接口,该接口定义了获取备忘录的方法:

type Memento interface {
    GetState() string
}

然后,我们定义 TextEditor 结构体,该结构体实现了 Originator 接口。TextEditor 结构体包含了一个字符串类型的 state 变量,它代表当前文本编辑器的状态:

type TextEditor struct {
    state string
}

func (t *TextEditor) Save() Memento {
    return &textMemento{state: t.state}
}

func (t *TextEditor) Restore(m Memento) {
    t.state = m.GetState()
}

func (t *TextEditor) SetState(state string) {
    t.state = state
}

func (t *TextEditor) GetState() string {
    return t.state
}

在 TextEditor 结构体中,Save 方法将当前的 state 变量封装在textMemento 结构体中并返回,而 Restore 方法将 state 变量恢复为 Memento 中存储的状态。此外,我们还定义了 SetState 和 GetState 方法,以便在其他地方获取和设置文本编辑器的状态。

下面是textMemento结构体的定义,该结构体实现了 Memento 接口,它保存了文本编辑器的状态:

type textMemento struct {
    state string
}

func (t *textMemento) GetState() string {
    return t.state
}

最后,我们定义 Caretaker 结构体,该结构体负责管理 Memento。Caretaker 结构体包含了一个 mementos 切片,它用于保存 Memento。Caretaker 结构体还包含了一个 currentIndex 变量,它代表当前状态的索引:

type Caretaker struct {
    mementos     []Memento
    currentIndex int
}

func (c *Caretaker) AddMemento(m Memento) {
    c.mementos = append(c.mementos, m)
    c.currentIndex = len(c.mementos) - 1
}

Caretaker 结构体的 Undo 方法用于撤销操作。它从 mementos 切片中获取上一个状态的 Memento,然后将文本编辑器的状态恢复为该 Memento 中存储的状态。该方法还将 currentIndex 变量减 1,以便在下一次 Undo 操作时返回正确的 Memento:

func (c *Caretaker) Undo(t *TextEditor) {
    if c.currentIndex > 0 {
        c.currentIndex--
        m := c.mementos[c.currentIndex]
        t.Restore(m)
    }
}

Caretaker 结构体的 Redo 方法用于重做操作。它从 mementos 切片中获取下一个状态的 Memento,然后将文本编辑器的状态恢复为该 Memento 中存储的状态。该方法还将 currentIndex 变量加 1,以便在下一次 Redo 操作时返回正确的 Memento:

func (c *Caretaker) Redo(t *TextEditor) {
    if c.currentIndex < len(c.mementos)-1 {
        c.currentIndex++
        m := c.mementos[c.currentIndex]
        t.Restore(m)
    }
}

最后,我们创建一个 TextEditor 实例和一个 Caretaker 实例,并测试我们的实现:

func main() {
    editor := &TextEditor{}
    caretaker := &Caretaker{}

    editor.SetState("State #1")
    caretaker.AddMemento(editor.Save())

    editor.SetState("State #2")
    caretaker.AddMemento(editor.Save())

    editor.SetState("State #3")
    caretaker.AddMemento(editor.Save())

    caretaker.Undo(editor)
    fmt.Println(editor.GetState())

    caretaker.Redo(editor)
    fmt.Println(editor.GetState())
}

在这个测试代码中,我们先设置文本编辑器的状态为 「State #1」,然后保存该状态的 Memento 并将其添加到 Caretaker 中。接着,我们将文本编辑器的状态设置为 「State #2」 并保存Memento,再将状态设置为「State #2」并保存 Memento。

接下来,我们调用 Caretaker 的 Undo 方法撤销一个操作,然后打印当前的文本编辑器状态。我们再调用 Caretaker 的 Redo 方法重做上一个操作,然后再次打印当前的文本编辑器状态。输出结果如下:

State #2
State #3

可以看到,我们成功地使用备忘录模式实现了文本编辑器的撤销和重做操作。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 查看所有版本


暂无话题~