首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

读《研磨设计形式》-代码笔记-备忘录模式-Memento

2012-12-20 
读《研磨设计模式》-代码笔记-备忘录模式-Memento声明:本文只为方便我个人查阅和理解,详细的分析以及源代码

读《研磨设计模式》-代码笔记-备忘录模式-Memento
声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/


import java.util.ArrayList;import java.util.List;/* * 备忘录模式的功能是,在不破坏封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,为以后的状态恢复作“备忘” * 书上给了一个场景,仿真系统: * 这个系统有两步操作,第一步操作后,产生一个临时数据(中间数据); * 接下来的第二步操作有两种方案,这两种方案都要基于第一步产生的数据作进一步处理 * 不用备忘录模式的处理方法是: * “客户端”调用时,自行创建一个变量来存储该对象第一步操作产生的临时数据, * 在第二步操作进行之前,把临时数据再set回到该对象 * 这就把实现细节暴露到“客户端”去了 * 看书看到这里时,我想,既然是两步操作共存临时数据又不想暴露给外部,可以用内部类来保存这些数据。接着看下去,果然是这样 * 另外,为达到“在对象之外保存这个状态”,书上的例子是把“备忘录”作为“备忘录管理者”的类成员来达到这个目的 * 在“仿真系统”这个例子,似乎不需要“在对象之外保存这个状态” *///不用模式的实现class WorkflowA {private String workflowName;//工作流名字private int tempResult;//临时计算结果private String tempState;//临时状态public WorkflowA(String workflowName) {this.workflowName = workflowName;}public void stepOne() {this.tempResult = 1;this.tempState = "State of stepOne.";}public void stepTwoSchema1() {this.tempResult += 21;this.tempState += "--> State of stepTwo by schema1.";System.out.println(this.workflowName + " Schema1. result = " + this.tempResult + " state = " + this.tempState);}public void stepTwoSchema2() {this.tempResult += 22;this.tempState += "--> State of stepTwo by schema2.";System.out.println(this.workflowName + " Schema2. result = " + this.tempResult + " state = " + this.tempState);}public int getTempResult() {return tempResult;}public void setTempResult(int tempResult) {this.tempResult = tempResult;}public String getTempState() {return tempState;}public void setTempState(String tempState) {this.tempState = tempState;}public String getWorkflowName() {return workflowName;}}//使用备忘录模式//备忘录。是一个“窄接口”,空接口interface IMemento {}/* * WorkflowB在业务逻辑上是和WorkflowA一样的,但增加了备忘录 * 这里为了偷懒,直接extends WorkflowA了,实际应用中不应该这样 */class WorkflowB extends WorkflowA implements Cloneable{public WorkflowB(String workflowName) {super(workflowName);}public IMemento createMemento() {return new MementoImpl(this.getTempResult(), this.getTempState());}//备忘录private static class MementoImpl implements IMemento {private int tempResult;private String tempState;MementoImpl(int tempResult, String tempState) {this.tempResult = tempResult;this.tempState = tempState;}//提供get方法就好了public int getTempResult() {return tempResult;}public String getTempState() {return tempState;}}//恢复数据到“临时状态”-执行了第一步操作之后public void setMemento(IMemento memento) {MementoImpl mementoo = (MementoImpl)memento;this.setTempResult(mementoo.getTempResult());this.setTempState(mementoo.getTempState());}}//结合原型模式(Prototype)class WorkflowC extends WorkflowA implements Cloneable{public WorkflowC(String workflowName) {super(workflowName);}public IMemento createMemento() {try {return new MementoImpl((WorkflowC) this.clone());//实际应用中要注意浅克隆的问题} catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}public void setMemento(IMemento memento) {MementoImpl mementoo = (MementoImpl)memento;this.setTempResult(mementoo.getWorkflow().getTempResult());this.setTempState(mementoo.getWorkflow().getTempState());}private static class MementoImpl implements IMemento {private WorkflowC workflow;public MementoImpl(WorkflowC workflow) {this.workflow = workflow;}public WorkflowC getWorkflow() {return workflow;}}}//备忘录管理者 持有了备忘录对象,可把备忘录对象保存到想保存的地方,例如后面提到的保存到xml文件中class CareTaker {private IMemento memento;public void saveMemento(IMemento memento) {this.memento = memento;//这里可以保存到其他地方去,例如写到文件中}public IMemento retriveMemento() {return this.memento;//如果是保存到文件中了,这里就是读文件}}//扩展:使用备忘录模式来实现可撤销的操作。可与命令模式的实现作对比interface ICommand {public void execute();public void undo(IMemento memento);public void redo(IMemento memento);public IMemento createMemento();}interface IOperation {public int getResult();public void add(int num);//加上numpublic void substract(int num);//减去numpublic IMemento createMemento();public void setMemento(IMemento memento);}//将Command的一些公共操作提取到抽象的父类中去abstract class AbstractCommand implements ICommand {protected IOperation operation;public void setOperation(IOperation operation) {this.operation = operation;}public IMemento createMemento() {return this.operation.createMemento();}//不管是撤销操作还是恢复操作,实际都是从备忘录中恢复到指定的状态public void redo(IMemento memento) {this.operation.setMemento(memento);}public void undo(IMemento memento) {this.operation.setMemento(memento);}//具体是什么操作,交由子类来实现public abstract void execute();}class AddCommand extends AbstractCommand {private int num;//加数,增量public void execute() {this.operation.add(num);}public AddCommand(int num) {this.num = num;}}class SubstractCommand extends AbstractCommand {private int num;//减数public void execute() {this.operation.substract(num);}public SubstractCommand(int num) {this.num = num;}}class Operation implements IOperation {private int result;//被加数 or 被减数public void add(int num) {this.result += num;}public void substract(int num) {this.result -= num;}public IMemento createMemento() {return new Memento(this.result);}public int getResult() {return result;}public void setMemento(IMemento memento) {Memento mementoo = (Memento)memento;this.result = mementoo.getResult();}private static class Memento implements IMemento {public Memento(int result) {this.result = result;}private int result;public int getResult() {return result;}public void setResult(int result) {this.result = result;}}}class Caculator {private List<ICommand> undoCmds = new ArrayList<ICommand>();private List<ICommand> redoCmds = new ArrayList<ICommand>();//IMemento[2]:两个Memento,一个是操作前,一个是操作后private List<IMemento[]> undoMementos = new ArrayList<IMemento[]>();private List<IMemento[]> redoMementos = new ArrayList<IMemento[]>();private ICommand addCommand;private ICommand substractCommand;public void addPressed() {IMemento mementoBefore = addCommand.createMemento();addCommand.execute();undoCmds.add(addCommand);IMemento mementoAfter = addCommand.createMemento();undoMementos.add(new IMemento[]{mementoBefore, mementoAfter});}public void substractPressed() {IMemento mementoBefore = addCommand.createMemento();substractCommand.execute();undoCmds.add(substractCommand);IMemento mementoAfter = substractCommand.createMemento();undoMementos.add(new IMemento[]{mementoBefore, mementoAfter});}public void undoPress() {if (undoCmds.size() > 0) {ICommand cmd = undoCmds.get(undoCmds.size() - 1);IMemento[] mementos = undoMementos.get(undoMementos.size() - 1);cmd.undo(mementos[0]);redoCmds.add(cmd);redoMementos.add(mementos);undoCmds.remove(cmd);undoMementos.remove(mementos);} else {System.out.println("没有可撤销的命令");}}public void redoPressed() {if (redoCmds.size() > 0) {ICommand cmd = redoCmds.get(redoCmds.size() - 1);IMemento[] mementos = redoMementos.get(redoMementos.size() - 1);cmd.redo(mementos[1]);undoCmds.add(cmd);undoMementos.add(mementos);redoCmds.remove(cmd);redoMementos.remove(mementos);} else {System.out.println("没有可恢复的命令");}}public void setAddCommand(ICommand addCommand) {this.addCommand = addCommand;}public void setSubstractCommand(ICommand substractCommand) {this.substractCommand = substractCommand;}}//这个类是用来测试的public class MementoPattern {public static void main(String[] args) {//测试不使用模式WorkflowA flow = new WorkflowA("WorkflowA");flow.stepOne();//下面两句是客户端在调用时作备份,将WorkflowA的实现细节暴露给客户端了int tempResult = flow.getTempResult();String tempState = flow.getTempState();flow.stepTwoSchema1();flow.setTempResult(tempResult);flow.setTempState(tempState);flow.stepTwoSchema2();//测试使用备忘录模式WorkflowB flowB = new WorkflowB("WorkflowB");flowB.stepOne();//保存“临时状态”IMemento memento = flowB.createMemento();CareTaker taker = new CareTaker();taker.saveMemento(memento);flowB.stepTwoSchema1();//恢复到“临时状态”flowB.setMemento(taker.retriveMemento());flowB.stepTwoSchema2();//测试使用备忘录模式与原型模式结合WorkflowC flowC = new WorkflowC("WorkflowC");flowC.stepOne();//保存“临时状态”memento = flowC.createMemento();taker = new CareTaker();taker.saveMemento(memento);flowC.stepTwoSchema1();//恢复到“临时状态”flowC.setMemento(taker.retriveMemento());flowC.stepTwoSchema2();//测试备忘录模式结合命令模式实现可撤销的操作IOperation operation = new Operation();AddCommand addCommand = new AddCommand(5);SubstractCommand substractCommand = new SubstractCommand(3);addCommand.setOperation(operation);substractCommand.setOperation(operation);Caculator caculator = new Caculator();caculator.setAddCommand(addCommand);caculator.setSubstractCommand(substractCommand);caculator.addPressed();System.out.println("一次加法(加5)操作后的结果是:" + operation.getResult());caculator.substractPressed();System.out.println("一次减法(减3)操作后的结果是:" + operation.getResult());caculator.undoPress();System.out.println("撤销一次操作后的结果是:" + operation.getResult());caculator.undoPress();System.out.println("再撤销一次操作后的结果是:" + operation.getResult());caculator.redoPressed();System.out.println("恢复一次操作的结果是:" + operation.getResult());caculator.redoPressed();System.out.println("再恢复一次操作的结果是:" + operation.getResult());}}

热点排行