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)
}