Go和Java实现备忘录模式
下面通过一个保存游戏进度的案例来说明备忘录模式的使用。
1、备忘录模式
备忘录模式保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
-
意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
-
主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个
状态,这样可以在以后将对象恢复到原先保存的状态。
-
何时使用:很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者
错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。
-
如何解决:通过一个备忘录类专门存储对象状态。
-
关键代码:客户不与备忘录类耦合,与备忘录管理类耦合。
-
应用实例: 1、后悔药。 2、打游戏时的存档。 3、Windows 里的 ctrl + z。 4、IE 中的后退。 5、数据库的事
务管理。
-
优点:1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 2、实
现了信息的封装,使得用户不需要关心状态的保存细节。
-
缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
-
使用场景:1、需要保存/恢复数据的相关状态场景。 2、提供一个可回滚的操作。
-
注意事项:1、为了符合迪米特原则,还要增加一个管理备忘录的类。 2、为了节约内存,可使用原型模式+备
忘录模式。
-
适用性:
必须保存一个对象在某一个时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。
如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
2、Go实现备忘录模式
package memento// ========== 角色状态存储箱RoleStateMemento ==========
// 备忘录存储原发器对象的内部状态
type RoleStateMemento struct {// 生命力vit int// 攻击力atk int// 防御力def int
}func NewRoleStateMemento(vit, atk, def int) RoleStateMemento {return RoleStateMemento{vit: vit,atk: atk,def: def,}
}
package mementoimport "fmt"// ========== 游戏角色GameRole ==========
// 原发器创建一个备忘录,用以记录当前时刻的内部状态,使用备忘录恢复内部状态
type GameRole struct {// 生命力vit int// 攻击力atk int// 防御力def int
}// 状态显示
func (gameRole *GameRole) StateDisplay() {fmt.Println("角色当前状态: ")fmt.Println("体力: ", gameRole.vit)fmt.Println("攻击力: ", gameRole.atk)fmt.Println("防御力: ", gameRole.def)
}// 获得初始状态
func (gameRole *GameRole) GetInitState() {gameRole.vit = 100gameRole.atk = 100gameRole.def = 100
}// 战斗
func (gameRole *GameRole) Fight() {gameRole.vit = 0gameRole.atk = 0gameRole.def = 0
}// 保存角色状态
func (gameRole *GameRole) SaveState() RoleStateMemento {return NewRoleStateMemento(gameRole.vit, gameRole.atk, gameRole.def)
}// 恢复角色状态
func (gameRole *GameRole) RecoveryState(roleStateMemento RoleStateMemento) {gameRole.vit = roleStateMemento.vitgameRole.atk = roleStateMemento.atkgameRole.def = roleStateMemento.def
}
package memento// ========== 角色状态管理者RoleStateCaretaker ==========
// 负责保存好备忘录,不能对备忘录的内部进行操作或检查
type RoleStateCaretaker struct {roleStateMemento RoleStateMemento
}func (roleStateCaretaker *RoleStateCaretaker) GetRoleStateMemento() RoleStateMemento {return roleStateCaretaker.roleStateMemento
}func (roleStateCaretaker *RoleStateCaretaker) SetRoleStateMemento(roleStateMemento RoleStateMemento) {roleStateCaretaker.roleStateMemento = roleStateMemento
}
package mainimport . "proj/memento"func main() {gameRole := GameRole{}gameRole.GetInitState()gameRole.StateDisplay()// 保存进度roleStateCaretaker := RoleStateCaretaker{}roleStateCaretaker.SetRoleStateMemento(gameRole.SaveState())// 进行战斗gameRole.Fight()gameRole.StateDisplay()// 恢复之前状态gameRole.RecoveryState(roleStateCaretaker.GetRoleStateMemento())gameRole.StateDisplay()}
# 程序输出
角色当前状态:
体力: 100
攻击力: 100
防御力: 100
角色当前状态:
体力: 0
攻击力: 0
防御力: 0
角色当前状态:
体力: 100
攻击力: 100
防御力: 100
3、Java备忘录模式
package com.memento;// ========== 角色状态存储箱RoleStateMemento ==========
// 备忘录存储原发器对象的内部状态
public class RoleStateMemento {// 生命力private int vit;// 攻击力private int atk;// 防御力private int def;public RoleStateMemento(int vit,int atk,int def){this.vit = vit;this.atk = atk;this.def = def;}public int getVit() {return vit;}public void setVit(int vit) {this.vit = vit;}public int getAtk() {return atk;}public void setAtk(int atk) {this.atk = atk;}public int getDef() {return def;}public void setDef(int def) {this.def = def;}}
package com.memento;// ========== 游戏角色GameRole ==========
// 原发器创建一个备忘录,用以记录当前时刻的内部状态,使用备忘录恢复内部状态
public class GameRole {// 生命力private int vit;// 攻击力private int atk;// 防御力private int def;public int getVit() {return vit;}public void setVit(int vit) {this.vit = vit;}public int getAtk() {return atk;}public void setAtk(int atk) {this.atk = atk;}public int getDef() {return def;}public void setDef(int def) {this.def = def;}// 状态显示public void stateDisplay(){System.out.println("角色当前状态: ");System.out.println("体力: "+this.vit);System.out.println("攻击力: "+this.atk);System.out.println("防御力: "+this.def);}// 获得初始状态public void getInitState(){this.vit = 100;this.atk = 100;this.def = 100;}// 战斗public void fight(){this.vit = 0;this.atk = 0;this.def = 0;}// 保存角色状态public RoleStateMemento saveState(){return new RoleStateMemento(vit,atk,def);}// 恢复角色状态public void recoveryState(RoleStateMemento roleStateMemento){this.vit = roleStateMemento.getVit();this.atk = roleStateMemento.getAtk();this.def = roleStateMemento.getDef();}
}
package com.memento;// ========== 角色状态管理者RoleStateCaretaker ==========
// 负责保存好备忘录,不能对备忘录的内部进行操作或检查
public class RoleStateCaretaker {private RoleStateMemento roleStateMemento;public RoleStateMemento getRoleStateMemento() {return roleStateMemento;}public void setRoleStateMemento(RoleStateMemento roleStateMemento) {this.roleStateMemento = roleStateMemento;}
}
package com.memento;public class Test {public static void main(String[] args) {GameRole gameRole = new GameRole();gameRole.getInitState();gameRole.stateDisplay();// 保存进度RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();roleStateCaretaker.setRoleStateMemento(gameRole.saveState());// 进行战斗gameRole.fight();gameRole.stateDisplay();// 恢复之前状态gameRole.recoveryState(roleStateCaretaker.getRoleStateMemento());gameRole.stateDisplay();}
}
# 程序输出
角色当前状态:
体力: 100
攻击力: 100
防御力: 100
角色当前状态:
体力: 0
攻击力: 0
防御力: 0
角色当前状态:
体力: 100
攻击力: 100
防御力: 100