什么是备忘录模式?
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存着这个状态。这样以后就可将该对象恢复到原先保存的状态。
实现
// 游戏角色
type GameRole struct {
Vit int // 生命力
Atk int // 攻击力
Def int // 防御力
}
func NewGameRole() *GameRole {
return &GameRole{}
}
func (this *GameRole) SetVit(vit int) {
this.Vit = vit
}
func (this *GameRole) SetAtk(atk int) {
this.Atk = atk
}
func (this *GameRole) SetDef(def int) {
this.Def = def
}
func (this *GameRole) GetVit() int {
return this.Vit
}
func (this *GameRole) GetAtk() int {
return this.Atk
}
func (this *GameRole) GetDef() int {
return this.Def
}
//状态显示
func (this *GameRole) StateDisplay() {
fmt.Println("角色当前状态:")
fmt.Println("体力:", this.Vit)
fmt.Println("攻击力:", this.Atk)
fmt.Println("防御力: ", this.Def)
fmt.Println("--------------------------")
}
// 初始值
func (this *GameRole) GetInitState() {
this.Vit = 100
this.Atk = 100
this.Def = 100
}
// 战斗后
func (this *GameRole) AfterFight() {
this.Vit = 0
this.Atk = 0
this.Def = 0
}
// 保存角色状态
func (this *GameRole) SaveState(vit, atk, def int) RoleStateMemento {
return NewRoleStateMemento(vit, atk, def)
}
// 恢复角色状态
func (this *GameRole) RecoveryState(memento RoleStateMemento) {
this.Vit = memento.GetVit()
this.Atk = memento.GetAtk()
this.Def = memento.GetDef()
}
// 角色状态存储
type RoleStateMemento struct {
Vit int // 生命力
Atk int // 攻击力
Def int // 防御力
}
func NewRoleStateMemento(vit, atk, def int) RoleStateMemento {
return RoleStateMemento{Vit: vit, Atk: atk, Def: def}
}
func (this *RoleStateMemento) SetVit(vit int) {
this.Vit = vit
}
func (this *RoleStateMemento) SetAtk(atk int) {
this.Atk = atk
}
func (this *RoleStateMemento) SetDef(def int) {
this.Def = def
}
func (this *RoleStateMemento) GetVit() int {
return this.Vit
}
func (this *RoleStateMemento) GetAtk() int {
return this.Atk
}
func (this *RoleStateMemento) GetDef() int {
return this.Def
}
// 角色状态管理
type RoleStateCaretaker struct {
memento RoleStateMemento
}
func (this *RoleStateCaretaker) GetMemento() RoleStateMemento {
return this.memento
}
func NewRoleStateCaretaker() *RoleStateCaretaker {
return &RoleStateCaretaker{}
}
func (this *RoleStateCaretaker) SetMemento(memento RoleStateMemento) {
this.memento = memento
}
func TestNewRoleStateCaretaker(t *testing.T) {
// 初始化
gameRole := NewGameRole()
gameRole.GetInitState()
gameRole.StateDisplay()
// 保存进度
caretaker := NewRoleStateCaretaker()
caretaker.SetMemento(gameRole.SaveState(44, 55, 66))
// 打BOSS失败
gameRole.AfterFight()
gameRole.StateDisplay()
// 恢复状态
gameRole.RecoveryState(caretaker.GetMemento())
gameRole.StateDisplay()
}
// === RUN TestNewRoleStateCaretaker
// 角色当前状态:
// 体力: 100
// 攻击力: 100
// 防御力: 100
// --------------------------
// 角色当前状态:
// 体力: 0
// 攻击力: 0
// 防御力: 0
// --------------------------
// 角色当前状态:
// 体力: 44
// 攻击力: 55
// 防御力: 66
// --------------------------
// --- PASS: TestNewRoleStateCaretaker (0.00s)
// PASS
优点
- 给用户提供了一种可以恢复状态的机制,可以使用能够比较方便地回到某个历史的状态;
- 实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点
- 消耗资源。
使用场景
- 需要保存和恢复数据的相关场景;
- 提供一个可回滚的操作,如ctrl+z、浏览器回退按钮、Backspace键等;
- 需要监控的副本场景。
应用实例
- 游戏存档,悔棋;
- 数据库事务回滚。
注意
- 为了符合迪米特法则,需要有一个管理备忘录的类;
- 不要在频繁建立备份的场景中使用备忘录模式。为了节约内存,可使用原型模式+备忘录模式。
网友评论