本文共 9332 字,大约阅读时间需要 31 分钟。
备忘录模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
这个模式也很简单,最主要是一种思想。逻辑缜密的人在设计框架时必然走到这里。我们看看UML类图。
基本逻辑代码:
class Originator{ private String state; public Memento createMemento(){ return (new Memento(state)); } public void setMemento(Memento m{ state = m.state; } public void show(){ //输出state }}
class Memento{ private String state; public Memento(String state){ this.state = state; } poublic String getState(){ return state; }}
class Caretaker{ private Memento m; public void saveMemento(Memento m){ this.m = m;} public Memento getMemento(){ return m; }}客户端调用
static void mian(String[] args){ Originator o = new Originator(); o.state = "on"; Caretaker c = new Caretaker(); c.setMemento(o.createMemento()); o.state = "off"; o.setMemento(c.getMemento()):}代码一看都能明白,很简单。相信大家很多人小时候都玩过卡带游戏,带保存进度的那种游戏。每次在一个节点保存进度,在进入下一个节点,一旦失败了。可以恢复节点处的状态,这个就是典型的备忘录模式。这里就以游戏有例子。
备忘录类
package com.abings.mementomodel.MementoModel;/** * Created by HaomingXu on 2016/9/13. */public class Memento { public String name;//姓名 public String sex;//性别 public String style;//职业 public String attckZB;//攻击装备 public String defineZB;//防御装备 public String lifeZB;//指环装备 public int attack;//攻击力 public int define;//防御值 public int life;//生命值 public int lan;//法力值 public Memento(String name, String sex, String style, String attckZB, String defineZB, String lifeZB, int attack, int define, int life, int lan) { this.name = name; this.sex = sex; this.style = style; this.attckZB = attckZB; this.defineZB = defineZB; this.lifeZB = lifeZB; this.attack = attack; this.define = define; this.life = life; this.lan = lan; } public Memento(){ } public int getLan() { return lan; } public void setLan(int lan) { this.lan = lan; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getStyle() { return style; } public void setStyle(String style) { this.style = style; } public String getAttckZB() { return attckZB; } public void setAttckZB(String attckZB) { this.attckZB = attckZB; } public String getDefineZB() { return defineZB; } public void setDefineZB(String defineZB) { this.defineZB = defineZB; } public String getLifeZB() { return lifeZB; } public void setLifeZB(String lifeZB) { this.lifeZB = lifeZB; } public int getAttack() { return attack; } public void setAttack(int attack) { this.attack = attack; } public int getDefine() { return define; } public void setDefine(int define) { this.define = define; } public int getLife() { return life; } public void setLife(int life) { this.life = life; } @Override public String toString() { return "玩家{" + "姓名:'" + name + '\'' + "\n 性别:'" + sex + '\'' + "\n 职业:'" + style + '\'' + "\n 攻击装备:'" + attckZB + '\'' + "\n 防御装备:'" + defineZB + '\'' + "\n 指环:'" + lifeZB + '\'' + "\n 攻击力:" + attack + "\n 防御力:" + define + "\n 生命值:" + life + "\n 魔法值:" + lan + '}'; }}玩家类
package com.abings.mementomodel.Builder;import com.abings.mementomodel.MementoModel.Memento;/** * Created by HaomingXu on 2016/9/13. */public class Player extends Memento { public Player(String name, String sex, String style, String attckZB, String defineZB, String lifeZB, int attack, int define, int life, int lan) { super(name, sex, style, attckZB, defineZB, lifeZB, attack, define, life, lan); } public Player(){ } //创建备忘录 public Memento createMemento(){ return (new Memento(name,sex,style,attckZB,defineZB,lifeZB,attack,define,life,lan)); } //恢复状态 public void setMemento(Memento memento){ this.name = memento.getName(); this.sex = memento.getSex(); this.style = memento.getStyle(); this.attckZB = memento.getAttckZB(); this.defineZB = memento.getDefineZB(); this.lifeZB = memento.getLifeZB(); this.attack = memento.getAttack(); this.define = memento.getDefine(); this.life = memento.getLife(); this.lan = memento.getLan(); } public void fightWithBoss(){ this.life = 0; this.lan = 0; } @Override public String toString() { return super.toString(); }}
package com.abings.mementomodel.Builder;/** * Created by HaomingXu on 2016/9/13. */public abstract class Builder { public abstract void setLan() ; public abstract void setName() ; public abstract void setSex() ; public abstract void setStyle() ; public abstract void setAttckZB() ; public abstract void setDefineZB() ; public abstract void setLifeZB() ; public abstract void setAttack() ; public abstract void setDefine() ; public abstract void setLife() ; public abstract Player getPlayer();}建造者中指挥者
package com.abings.mementomodel.Builder;/** * Created by HaomingXu on 2016/9/13. */public class Director { public static Player cratePlayer(Builder builder){ builder.setName(); builder.setSex(); builder.setAttack(); builder.setAttckZB(); builder.setDefine(); builder.setDefineZB(); builder.setLan(); builder.setLifeZB(); builder.setLife(); builder.setStyle(); return builder.getPlayer(); }}
package com.abings.mementomodel.MementoModel;/** * Created by HaomingXu on 2016/9/13. */public class Caretaker { private Memento memento; public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; }}客户端
package com.abings.mementomodel;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import com.abings.mementomodel.Builder.Director;import com.abings.mementomodel.Builder.Player;import com.abings.mementomodel.Builder.ZhanShiPlayer;import com.abings.mementomodel.MementoModel.Caretaker;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建角色,魔族战士 Player player = Director.cratePlayer(new ZhanShiPlayer()); //到了保存记录节点 Caretaker caretaker = new Caretaker(); //打boss之前保存状态 caretaker.setMemento(player.createMemento()); //打Boss之前的状态 Log.i("Tag", player.toString()); //单挑BOSS失败了 player.fightWithBoss(); //单挑之后的状态 Log.i("Tag", player.toString()); //读取记录,满血复活 player.setMemento(caretaker.getMemento()); //读取记录之后的状态 Log.i("Tag", player.toString()); }}运行结果:
09-13 12:58:13.615 27181-27181/com.abings.mementomodel I/Tag: 玩家{姓名:'魔尊重楼' 性别:'男' 职业:'魔族战士' 攻击装备:'魔族至尊饮血剑' 防御装备:'魔族至尊反甲' 指环:'魔族至尊狂澜铠甲' 攻击力:3500 防御力:3000 生命值:6000 魔法值:1500}09-13 12:58:13.615 27181-27181/com.abings.mementomodel I/Tag: 玩家{姓名:'魔尊重楼' 性别:'男' 职业:'魔族战士' 攻击装备:'魔族至尊饮血剑' 防御装备:'魔族至尊反甲' 指环:'魔族至尊狂澜铠甲' 攻击力:3500 防御力:3000 生命值:0 魔法值:0}09-13 12:58:13.615 27181-27181/com.abings.mementomodel I/Tag: 玩家{姓名:'魔尊重楼' 性别:'男' 职业:'魔族战士' 攻击装备:'魔族至尊饮血剑' 防御装备:'魔族至尊反甲' 指环:'魔族至尊狂澜铠甲' 攻击力:3500 防御力:3000 生命值:6000 魔法值:1500}运用起来也很简单,客户端代码相当简洁。代码的扩展性,灵活性,维护性,可复用性都得到了一定的提升。只是这里面的逻辑有点绕。多学多用才是真理、git: