`

读《研磨设计模式》-代码笔记-备忘录模式-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);		//加上num
	
	public void substract(int num);		//减去num
	
	public 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());
		
		
	}

}

0
1
分享到:
评论

相关推荐

    c++设计模式-行为型模式-备忘录模式

    c++设计模式-行为型模式-备忘录模式;qt工程;c++简单源码;备忘录(Memento)模式的定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先...

    设计模式专题之(十九)备忘录模式---设计模式备忘录模式示例代码(python--c++)

    备忘录模式是一种行为设计模式,它允许在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态。这种模式通常用于游戏存档、撤销/重做操作、以及...

    java设计模式-备忘录模式源代码

    备忘录模式是一种在软件工程中广泛使用的面向对象设计模式,它主要用来安全地保存对象的状态,以便在需要时能够恢复到先前的状态。这个模式的名字来源于我们日常生活中使用的备忘录,它记录了一些重要的信息,当需要...

    设计模式-备忘录模式(讲解及其实现代码)

    备忘录模式是一种在软件工程中广泛使用的面向对象设计模式,它主要用来安全地保存对象的状态,以便在需要时能够恢复到先前的状态。备忘录模式的核心思想是封装对象的状态,将其保存到一个独立的对象(备忘录)中,而...

    研磨设计模式-part2

    第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第...

    研磨设计模式-part4

    第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第...

    研磨设计模式-part3

    第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第...

    Java设计模式-备忘录

    通过学习和实践备忘录模式,开发者可以更好地理解如何在Java中利用设计模式来解决实际问题,提高代码的可维护性和可扩展性。同时,备忘录模式与其他设计模式如工厂模式、观察者模式等结合使用,可以构建出更复杂的...

    设计模式之备忘录(memento)

    在压缩包文件"Design"中,可能包含了与备忘录模式相关的代码示例、示例项目的源代码或者相关工具的介绍。通过查看这些内容,你可以进一步加深对备忘录模式的理解,并将其应用到自己的项目中。 总的来说,备忘录模式...

    设计模式 - 备忘录模式(C++实例)

    备忘录模式是一种在不破坏封装性的前提下,捕获一个对象的状态,并允许在未来的某个时刻恢复这个状态的设计模式。这种模式在很多场景下都非常有用,例如在游戏中保存进度、在编辑器中撤销/重做操作等。备忘录模式的...

    设计模式-备忘录

    备忘录模式是一种常用的设计模式,它在软件工程中用于保存对象的状态,以便在需要时恢复到之前的状态。这种模式的主要目标是实现数据的安全存储,同时保持对象的封装性,避免对外部对象直接访问其内部状态。在iOS...

    设计模式之备忘录模式(Memento Pattern)

    备忘录模式(Memento Pattern)是软件设计模式中的一种行为模式,它的主要目的是在不破坏对象封装性的前提下,允许对象在特定时刻保存其内部状态,并能够在之后恢复到保存时的状态。这种模式广泛应用于撤销/重做功能...

    C#面向对象设计模式纵横谈(21):(行为型模式) Memento 备忘录模式

    备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将对象恢复到先前的状态。这种模式在需要撤销/重做功能、...

    设计模式之备忘录模式(Memento)

    备忘录模式(Memento Pattern)是设计模式中的一种行为模式,主要目的是在不违反封装原则的情况下,保存一个对象的内部状态,以便在需要时能够恢复到先前的状态。这种模式通常用于实现撤销/重做功能或者在游戏中保存...

    备忘录模式-极客学院-java-课件代码

    备忘录模式是一种行为设计模式,它允许在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将对象恢复到原先保存的状态。这种模式常用于需要撤销/重做操作的场景,或者在...

    java常用设计模式-备忘录模式

    备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装性的情况下捕获和恢复对象的内部状态。该模式通常用于需要撤销操作或恢复先前状态的情况下。备忘录模式包括三个主要组件:原始对象、备忘录...

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    - 备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的状态,并在该对象之外保存这个状态,以便以后恢复。 - 观察者模式(Observer):定义对象间的一种一对多依赖关系,当一个对象的状态发生改变时,...

    JAVA设计模式--备忘录模式.docx

    状态保存到备忘录中Memento memento = o.createMemento();// 改变原发器的状态o.setState("state 1");...在JAVA编程中,通过合理运用备忘录模式,可以提高代码的可维护性和可扩展性,同时增强系统的功能。

    java设计模式-备忘录模式

    Java设计模式中的备忘录模式(Memento Pattern)是一种用于保存对象状态的模式,以便在未来某一时刻能够恢复到之前的状态。这种模式的核心在于在不违反对象封装性的前提下,捕获对象的内部状态并将其存储起来。备忘...

    C++设计模式课件19_Memento_备忘录.pdf

    备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。在C++中实现备忘录模式通常涉及以下几个角色: 1. 发起人(Originator):创建一个备忘录,用以...

Global site tag (gtag.js) - Google Analytics