1.场景问题解决
1.1 场景描述
讨论一个游戏进度状态保存问题
游戏进度保存:对象状态,场景…,需要安全性,不能被非保存人读取到
如果在不使用数据库的情况下,怎么设计
1.2 OO设计
保存在数据库中
1.3 需求变动
1.4 带来问题
2.用设计模式改进
2.1 分析
[外链图片转存失败(img-4IaLCwOf-1568819792579)(https://raw.githubusercontent.com/bobshute/public/master/imgs/csdn/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/21%E5%A4%87%E5%BF%98%E5%BD%95%E6%A8%A1%E5%BC%8F-1.png)]
2.2 重新设计
2.3 源码
- MementoIF 接口
- MementoCaretaker 管理者
public interface MementoIF {
}
public class MementoCaretaker {
private HashMap<String, MementoIF> mementomap;
public MementoCaretaker() {
mementomap = new HashMap<String, MementoIF>();
}
//恢复备忘录
public MementoIF retrieveMemento(String name) {
return mementomap.get(name);
}
/**
* 备忘录赋值方法-保存备忘录
*/
public void saveMemento(String name, MementoIF memento) {
this.mementomap.put(name, memento);
}
}
- Originator 发起者1,保存数据为HashMap
- Originator2 发起者2,保存数据为ArrayList
public class Originator {
private HashMap<String, String> state;
public Originator() {
state = new HashMap();
}
public MementoIF createMemento() {
return new Memento(state);
}
public void restoreMemento(MementoIF memento) {
state = ((Memento) memento).getState();
}
public void showState() {
System.out.println("now state:" + state.toString());
}
public void testState1() {
state.put("blood", "500");//游戏中自身血
state.put("progress", "gate1 end");//游戏进度
state.put("enemy", "5");//敌人数目
}
public void testState2() {
state.put("blood", "450");//游戏中自身血
state.put("progress", "gate3 start");//游戏进度
state.put("enemy", "3");//敌人数目
}
private class Memento implements MementoIF {
private HashMap<String, String> state;
private Memento(HashMap state) {
this.state = new HashMap(state);
}
private HashMap getState() {
return state;
}
private void setState(HashMap state) {
this.state = state;
}
}
}
public class Originator2 {
private ArrayList<String> state;
public Originator2() {
state = new ArrayList<String>();
}
public MementoIF createMemento() {
return new Memento(state);
}
public void restoreMemento(MementoIF memento) {
state = ((Memento) memento).getState();
}
public void testState1() {
state = new ArrayList<String>();
state.add("blood:320");
state.add("progress:gate2 mid");
state.add("enemy:15");
}
public void testState2() {
state = new ArrayList<String>();
state.add("blood:230");
state.add("progress:gate8 last");
state.add("enemy:12");
}
public void showState() {
System.out.println("now state:" + state.toString());
}
private class Memento implements MementoIF {
private ArrayList<String> state;
private Memento(ArrayList<String> state) {
this.state = new ArrayList(state);
}
private ArrayList<String> getState() {
return state;
}
private void setState(ArrayList<String> state) {
this.state = state;
}
}
}
- MementoTest 测试类
public class MementoTest {
public static void main(String[] args) {
MementoCaretaker mMementoCaretaker = new MementoCaretaker();
Originator mOriginator = new Originator();
Originator2 mOriginator2 = new Originator2();
System.out.println("*****Originator*****");
mOriginator.testState1();
mMementoCaretaker
.saveMemento("Originator", mOriginator.createMemento());
mOriginator.showState();
mOriginator.testState2();
mOriginator.showState();
mOriginator.restoreMemento(mMementoCaretaker
.retrieveMemento("Originator"));
mOriginator.showState();
System.out.println("*****Originator 2*****");
mOriginator2.testState1();
mOriginator2.showState();
mMementoCaretaker.saveMemento("Originator2",
mOriginator2.createMemento());
mOriginator2.testState2();
mOriginator2.showState();
mOriginator2.restoreMemento(mMementoCaretaker
.retrieveMemento("Originator2"));
mOriginator2.showState();
//如果保存和恢复不一致则报错
//System.out.println("*****Originator&&Originator 2*****");
// mOriginator.restoreMemento(mMementoCaretaker
// .retrieveMemento("Originator2"));
// mOriginator.showState();
}
}
3.设计模式总结
3.1 定义
备忘录模式:在不破坏封装的前提下,存储关键对象的重要状态,从而可以在将来把对象还原到存储的那个状态
3.2 分析思路
3.3 优缺点
- 优点:
状态存储在外面,不和关键对象混在一起,这可以帮助维护内聚
提供了容易实现的恢复能力
保持了关键对象的数据封装 - 缺点:
资源消耗上面备忘录对象会很昂贵
存储和恢复状态的过程比较耗时
4. 设计模式使用场景及注意
4.1 使用场景
必须保存一个对象在某一个时刻的(整体或部分)状态,在对象以外的地方, 以后需要时恢复到先前的状态时
5.参考文章
内容总计于HeadFirst设计模式及相关视频