文章目錄
- 1. 概述
- 1.1 角色
- 1.2 類圖
- 2. 代碼示例
- 2.1 設計
- 2.2 代碼
- 2.3 類圖
1. 概述
備忘錄(Memento)用于在不破壞目標對象封裝特性的基礎上,將目標對象內部的狀態存儲到外部對象中,以備之后恢復狀態時使用。
1.1 角色
- Originator(發起者):當前的基礎對象,它會將自己的狀態保存進備忘錄。
- savememento()方法:Originator通過該方法將它自己狀態保存進一個備忘錄對象。
- restorememento()方法:Originator通過該方法將它自己狀態回滾至指定備忘錄。
- Memento(備忘錄) : 存儲Originator狀態的對象
- Caretaker(管理者):保存多條備忘錄的對象,并維護著備忘錄的索引,在需要的時候會返回相應的備忘錄。
1.2 類圖
2. 代碼示例
2.1 設計
- 定義備忘錄
memento
來記錄發起者狀態 - 它的
Get()
方法獲取它的狀態 - 定義發起者
Originator
- 它的方法
CreateMemento()
用它自己創建一條備忘錄 - 它的方法
RollBack()
將它自己回滾至指定備忘錄的狀態 - 它的
Set()
方法可以設置它的狀態 - 它的
Get()
方法可以獲取它的狀態
- 它的方法
- 創建一個管理者
Caretaker
,它是備忘錄Memento
的聚合- 它的
AddMemento
方法,向它自身加入一條備忘錄 - 它的
GetMemento()
方法,查詢一條它管理的指定備忘錄
- 它的
- 調用
- 初始化
- 實例化一個管理者
caretaker
- 實例化一個發起者
originator
- 實例化一個管理者
- 創建備忘錄測試
- 第一次
- 用發起者創建一條備忘錄
- 管理者收錄該備忘錄
- 第二次
- 改變發起者狀態
- 用發起者創建一條新備忘錄
- 管理者收錄該備忘錄
- 第三次
- 改變發起者狀態
- 用發起者創建一條新備忘錄
- 管理者收錄該備忘錄
- 查看管理者信息,應該有三條備忘錄
- 第一次
- 回滾測試
- 從管理者獲取指定索引的備忘錄
- 將發起者回滾至該備忘錄狀態
- 初始化
2.2 代碼
- 代碼
package mainimport "fmt"// 定義備忘錄
type Memento struct {state string
}// 查備忘錄狀態
func (m *Memento) Get() string {return m.state
}// 定義發起者
type Originator struct {state string
}// 根據發起者狀態創建一條備忘錄
func (e *Originator) CreateMemento() (memento *Memento) {memento = &Memento{state: e.state}fmt.Printf("創建一條備忘錄:%+v\n", memento)return memento
}// 將發起者狀態回滾至指定備忘錄狀態
func (e *Originator) RollBack(m *Memento) {e.state = m.Get()fmt.Printf("發起者狀態回滾至:%v\n", e)
}// 設置發起者狀態
func (e *Originator) Set(state string) {e.state = statefmt.Println("發起者狀態更改為:", e.state)
}// 獲取發起者狀態
func (e *Originator) Get() string {fmt.Println("獲取發起者狀態為:", e.state)return e.state
}// 定義管理者,管理者是備忘錄的聚合
type Caretaker struct {mementoArray []*Memento
}// 向管理者中添加一條備忘錄
func (c *Caretaker) AddMemento(m *Memento) {fmt.Printf("向管理者中添加一條備忘錄:%+v\n", m)c.mementoArray = append(c.mementoArray, m)
}// 獲取指定備忘錄信息
func (c *Caretaker) GetMemento(index int) *Memento {fmt.Printf("獲取到第 %d 條備忘錄信息為:%+v\n", index, c.mementoArray[index])return c.mementoArray[index]
}func main() {//實例化一個管理者caretaker := &Caretaker{mementoArray: make([]*Memento, 0),}//實例化一個發起者originator := &Originator{state: "A",}//為發起者創建一條備忘錄memento0 := originator.CreateMemento()//在管理者中加入該備忘錄caretaker.AddMemento(memento0)//改變發起者狀態originator.Set("B")//為發起者創建第二條備忘錄memento1 := originator.CreateMemento()//在管理者中加入該備忘錄caretaker.AddMemento(memento1)//再次改變發起者狀態originator.Set("C")//為發起者創建第三條備忘錄memento2 := originator.CreateMemento()//在管理者中加入該備忘錄caretaker.AddMemento(memento2)fmt.Println("此時管理者應該有三條備忘錄:")for _, memento := range caretaker.mementoArray {fmt.Printf("%+v\n", memento)}fmt.Println("=========回滾測試===========")originator.RollBack(caretaker.GetMemento(1))fmt.Println("=========回滾測試===========")originator.RollBack(caretaker.GetMemento(0))
}
- 輸出
創建一條備忘錄:&{state:A}
向管理者中添加一條備忘錄:&{state:A}
發起者狀態更改為: B
創建一條備忘錄:&{state:B}
向管理者中添加一條備忘錄:&{state:B}
發起者狀態更改為: C
創建一條備忘錄:&{state:C}
向管理者中添加一條備忘錄:&{state:C}
此時管理者應該有三條備忘錄
&{state:A}
&{state:B}
&{state:C}
=========回滾測試===========
獲取到第 1 條備忘錄信息為:&{state:B}
發起者狀態回滾至:&{B}
=========回滾測試===========
獲取到第 0 條備忘錄信息為:&{state:A}
發起者狀態回滾至:&{A}