Go 设计模式之备忘录模式

103 阅读2分钟

Go设计模式之备忘录模式

备忘录模式是一种行为型设计模式,其中对象能够在不破坏其封装的前提下,捕获和恢复其内部状态。备忘录模式拥有三个核心角色:发起者、备忘录和管理者。下面我们一一介绍。

发起者

发起者是需要被保存状态的对象。为了将对象恢复到之前的状态,发起者需要创建一个副本来保存当前状态。在Go中,创建发起者可以像这样实现:

type Originator struct {
    state string
}

func (o *Originator) CreateMemento() *Memento {
    return &Memento{o.state}
}

func (o *Originator) SetMemento(m *Memento) {
    o.state = m.state
}

如上所示,环境类(在Go中是发起者)拥有一个状态变量 state。创建备忘录时,发起者在 Memento对象中存储其状态。恢复状态时,将状态还原为发起者原来的状态。

备忘录

备忘录是一个轻量级对象,主要用于保存发起者的状态。尽管可以确保安全地保存事务状态,但它并不表示发起者的完整历史记录。在Go中,这可以通过创建一个 Memento结构来实现:

type Memento struct {
    state string
}

发起者需要传递当前状态以创建备忘录。一旦备忘录被创建,备忘录将回传状态给发起者。

管理者

管理者是用于管理备忘录的类。在Go中,我们可以像这样实现CareTaker:

type CareTaker struct {
    mementos []*Memento
}

func (c *CareTaker) Add(m *Memento) {
    c.mementos = append(c.mementos, m)
}

func (c *CareTaker) Get(idx int) *Memento {
    return c.mementos[idx]
}

如上所示,CareTaker在一个列表中维护多个备忘录。当需要保存一个备忘录时,可以通过 Add方法将其添加到List列表中。获取备忘录时,可以使用 Get方法来检索它们。

使用备忘录模式

在应用程序中使用备忘录模式时,键是知道何时需要进行状态快照以及何时恢复它们。考虑以下代码:

func main() {
    originator := &Originator{state: "initial state"}
    fmt.Println(originator.state)
    careTaker := &CareTaker{mementos: []*Memento{}}
    careTaker.Add(originator.CreateMemento())

    originator.state = "updated state"
    fmt.Println(originator.state)

    originator.SetMemento(careTaker.Get(0))
    fmt.Println(originator.state)
}

在上面的示例中,我们将 Originator 的状态设置为“初始状态”,并调用其 CreateMemento 方法来保存当前状态。我们可以将该备忘录添加到CareTaker 中,之后 Originator 的状态被更新为“更新状态”。但是发生了什么问题?发起者现在希望将状态还原为之前的值,他可以使用我们在CareTaker 中为其保存的快照进行还原操作。

结论

备忘录模式允许我们在应用程序执行期间实现历史记录和状态还原.

完整代码

package main

import "fmt"

type Originator struct {
   state string
}

func (o *Originator) CreateMemento() *Memento {
   return &Memento{o.state}
}

func (o *Originator) SetMemento(m *Memento) {
   o.state = m.state
}

type Memento struct {
   state string
}

type CareTaker struct {
   mementos []*Memento
}

func (c *CareTaker) Add(m *Memento) {
   c.mementos = append(c.mementos, m)
}

func (c *CareTaker) Get(idx int) *Memento {
   return c.mementos[idx]
}

func main() {
   originator := &Originator{state: "initial state"}
   fmt.Println(originator.state)
   careTaker := &CareTaker{mementos: []*Memento{}}
   careTaker.Add(originator.CreateMemento())

   originator.state = "updated state"
   fmt.Println(originator.state)

   originator.SetMemento(careTaker.Get(0))
   fmt.Println(originator.state)
}