备忘录模式的定义为:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
备忘录模式很容易理解,实现起来也很简单。他相当于有一个第三方类,负责保存对象的状态,等待如果程序失败进行回滚。
万万没想到很多人看过,里面王大锤的很多场景就是典型的备忘录模式:
男人接口(尝试程序的接口):
/** * Men: 男人接口 * * @author xuejupo [email protected] create in 2015-12-30 上午10:16:51 * */ interface Men { /** * pursue: 每个男人都有追女生方法 * * @param msg * 追求的方法 void 返回类型 */ void pursue(String msg); }
女人接口(保存对象状态的接口):
/** * Women:女人接口 * * @author xuejupo [email protected] create in 2015-12-30 上午10:19:07 * */ interface Women extends Cloneable { /** * dealPursue: 每个女人都有对应的被追求的方法 * * @param msg * boolean 返回类型 表示同意否 */ boolean dealPursue(Men m, String msg); // 获得妹子名字 String getName(); // 女人应该可以被保存状态 public Women clone(); }
王大锤(尝试程序):
/** * Wangdachui: 王大锤 * * @author xuejupo [email protected] create in 2015-12-30 上午10:28:15 * */ class Wangdachui implements Men { // 我的目标 private Women target; /** * setTarget: 设定追求目标 * * @param target * void 返回类型 */ public void setTarget(Women target) { System.out.println("王大锤:哇,发现一个妹子:" + target.getName() + ",好可爱,我要追她,让她崇拜我,爱上我,对我欲罢不能~~"); this.target = target; } @Override public void pursue(String msg) { // TODO Auto-generated method stub if (this.target.dealPursue(this, msg)) { System.out .println("王大锤:哈哈," + this.target.getName() + "终于答应跟我在一起了"); } else { System.out.println("王大锤:一定是我太英俊了," + this.target.getName() + "自卑才不跟我在一起"); } } /** * createMemento: 创建备份录 * @return * Memento 返回类型 */ public Memento createMemento(){ return new Memento(this.target); } }
阿美:(需要保存状态进行回滚的对象)
/** * Amei: 阿美女神 * * @author xuejupo [email protected] create in 2015-12-30 上午10:31:24 * */ class Amei implements Women, Cloneable { // 女神的黑名单 private ArrayList<Men> blackList = new ArrayList<Men>(); @Override public boolean dealPursue(Men m, String msg) { // TODO Auto-generated method stub // 如果在女神黑名单,直接拜拜 if (this.blackList.contains(m)) { System.out.println("阿美:跟你说过不要找老娘了!"); return false; } // 女神是很物质的 if ("送钻戒".equals(msg) || "送别墅".equals(msg)) { System.out.println("阿美:看你这么有诚意,我就从了你把"); return true; } else { System.out.println("阿美:这点东西就想打动老娘,真以为老娘没见过市面呀!"); System.out.println("阿美:以后不要再来找老娘了!"); // 把追求者加入黑名单 this.blackList.add(m); return false; } } @Override public String getName() { // TODO Auto-generated method stub return "阿美"; } /** * clone: 重写的clone方法 * * @return * @throws CloneNotSupportedException * Object 返回类型 */ public Women clone() { // TODO Auto-generated method stub Amei amei = null; try { amei = (Amei) super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } amei.blackList = (ArrayList<Men>) this.blackList.clone(); return amei; } }
备忘录
/** * Memento: 备忘录,用于保存妹子状态 * * @author xuejupo [email protected] create in 2015-12-30 上午10:54:40 * */ class Memento { // 保存状态,只保存一种状态 public Women women; public Memento(Women women){ this.women = women.clone(); } public void setState(Women women) { this.women = women.clone(); } public Women getState() { return this.women; } }
测试代码:
public class MementoTest { /** * main: * * @param args * void 返回类型 */ public static void main(String[] args) { // TODO Auto-generated method stub testMemento(); } // 没有备忘录的测试程序 private static void testNoMemento() { // 王大锤出场 System.out.println("---------王大锤出场----------"); Wangdachui wang = new Wangdachui(); // 阿美出场 System.out.println("---------阿美----------"); Women amei = new Amei(); // 王大锤看上阿美 wang.setTarget(amei); // 王大锤给阿美送花 System.out.println("---------王大锤给阿美送花----------"); wang.pursue("送花"); System.out.println("---------王大锤约阿美逛街----------"); wang.pursue("逛街"); System.out.println("---------王大锤给阿美送钻戒----------"); wang.pursue("送钻戒"); } /** * testMemento: 测试备忘录 void 返回类型 */ private static void testMemento() { // 王大锤出场 System.out.println("---------王大锤出场----------"); Wangdachui wang = new Wangdachui(); // 阿美出场 System.out.println("---------阿美----------"); Women amei = new Amei(); // 王大锤看上阿美 wang.setTarget(amei); //追阿美之前先给阿美备份,万一追不到就回到起点: System.out.println("--------备份大法!---------"); Memento memento = wang.createMemento(); // 王大锤给阿美送花 System.out.println("---------王大锤给阿美送花----------"); wang.pursue("送花"); System.out.println("---------王大锤约阿美逛街----------"); wang.pursue("逛街"); System.out.println("-------看来阿美不理我了,幸好我有备份大法------"); wang.setTarget(memento.getState()); System.out.println("---------王大锤给阿美送钻戒----------"); wang.pursue("送钻戒"); } }
结果:
---------王大锤出场---------- ---------阿美---------- 王大锤:哇,发现一个妹子:阿美,好可爱,我要追她,让她崇拜我,爱上我,对我欲罢不能~~ --------备份大法!--------- ---------王大锤给阿美送花---------- 阿美:这点东西就想打动老娘,真以为老娘没见过市面呀! 阿美:以后不要再来找老娘了! 王大锤:一定是我太英俊了,阿美自卑才不跟我在一起 ---------王大锤约阿美逛街---------- 阿美:跟你说过不要找老娘了! 王大锤:一定是我太英俊了,阿美自卑才不跟我在一起 -------看来阿美不理我了,幸好我有备份大法------ 王大锤:哇,发现一个妹子:阿美,好可爱,我要追她,让她崇拜我,爱上我,对我欲罢不能~~ ---------王大锤给阿美送钻戒---------- 阿美:看你这么有诚意,我就从了你把 王大锤:哈哈,阿美终于答应跟我在一起了
备忘录的适用场景不是很多,最近我在做项目的时候碰到一种:我们的项目用户修改用户信息需要修改好几个表。如果用户修改某一个表失败,应该将用户修改过的其他的表回滚回用户修改前的状态。这种情况很适合用备忘录模式。