【学习笔记】命令模式与备忘录之简单计算器

挺长时间没写博文了,发现如果要写一篇(个人感觉上的)比较完整的博文,还是需要花费挺长的时间的,前阵子忙着一些资料复习,没能动手写笔记心得与实验。虽然写文章挺耗费时间的, 但是所能得到的也很多,在写的过程,会不断推敲内容,考虑如何写得不单自己明白,他人阅读时也能很容易看的明白,并重新整理下记忆内容,极大的加深记忆。所以,还是希望自己能尽可能的整理自己所学吧。谨以此勉励自己。

这篇文章所主要包含行为模式中的2个模式:命令模式&备忘录模式。

  • 命令模式是将行为封装成一个命令,然后将命令添加到调用者内,再由调用者发送给真正的处理者。这模式的解释说明对我来说有点绕,不过它的实现原理上很简单,就是通过调用者调用处理者执行命令的方式(就这么一句话),在本案例的计算器中,计算器作为调用者,命令是四则运算操作,计算类作为真正处理者,这样就对于计算器与计算类进行了解耦。

  • 备忘录模式这是比较简单,就是在不破坏封装的情况下,记录下一个对象的某个状态,以便进行恢复操作。这个实现起来就更为简单了,用一个状态类来记录对象的状态属性,在备忘录类中添加状态类对象(也可以是对象列表,取决于需求),在需要记录操作处调用备忘录捕获,在恢复处调用备忘录还原。在该计算器案例中,备忘录类作为计算类私有内部类存在,即除了该计算类对象,谁也无法操作它。

整个案例关系图如下:
【学习笔记】命令模式与备忘录之简单计算器_第1张图片

调用者类

package calc;

import impl.AbstractCommand;

public class Calculator {
	private AbstractCommand command;
	
	public Calculator(){
	}
	
	public void setCommand(AbstractCommand command){
		this.command = command;
	}
	
	public int compute(int value){
		int res = command.execute(value);
		System.out.println(res);
		return res;
	}
	
	public int undo(){
		int res = command.undo();
		System.out.println("撤销操作,当前结果为" + res);
		return  res;
	}
	
	public int redo(){
		int res = command.redo();
		System.out.println("取消撤销操作,当前结果为" + res);
		return res;
	}
	
	public int display(){
		int res = command.display();
		System.out.println("计算结果为:" + res);
		return res;
	}

}

处理者类:

package calc;

import java.util.ArrayList;
import java.util.List;

public class Calcute {
	private int sum;
	private Memento mto;
	
	public Calcute(){
		sum = 0;
		mto = new Memento();
	}
	
	public Calcute(int n){
		sum = n;
		mto = new Memento(n);
	}
	
	public int add(int value){
		sum += value;
		mto.todo(sum);
		return sum;
	}
	
	public int substract(int value){
		sum -= value;
		mto.todo(sum);
		return sum;
	}
	
	public int multiply(int value){
		sum *= value;
		mto.todo(sum);
		return sum;
	}
	
	public int divide(int value){
		sum /= value;
		mto.todo(sum);
		return sum;
	}
	
	public int undo(){
		this.sum = mto.undo();
		return sum;
	}
	
	public int redo(){
		this.sum = mto.redo();
		return sum;
	}
	
	public int getSum(){
		return sum;
	}
	
	private class Memento{
		private List<State> history;
		private State pre;
		
		private Memento(){
			history = new ArrayList<State>();
			history.add(new State(0));
		}
		
		private Memento(int n){
			history = new ArrayList<State>();
			history.add(new State(n));
		}
		
		private void todo(int value){
			history.add(new State(value));
		}
		
		private int undo(){
			if(history.size() > 1){
				pre = history.remove(history.size() -1);
			}
			return history.get(history.size() -1).getValue();
		}
		
		private int redo(){
			if(pre != null){
				history.add(pre);
				pre = null;
			}
			return history.get(history.size() - 1).getValue();
		}
	}
}

命令接口:

package impl;

import calc.Calcute;

public abstract class  AbstractCommand {
	protected Calcute calc;
	
	public AbstractCommand(Calcute calc){
		this.calc = calc;
	}
	
	public abstract int  execute(int value);
	public int undo() {
		return calc.undo();
	}
	public int redo() {
		return calc.redo();
	}
	public int display(){
		return calc.getSum();
	}
}

加法命令:

package command;

import calc.Calcute;
import impl.AbstractCommand;

public class AddCommand extends AbstractCommand{
	
	public AddCommand(Calcute calc){
		super(calc);
	}

	@Override
	public int execute(int value) {
		return calc.add(value);
	}
}
  • 整个案例以命令模式+备忘录模式的方式实现,计算操作都是以整数的结果来传递,这点在计算除法会出现问题,而且,对于除法操作上,需要更为详细的处理而不是简单的’’/"来进行!

  • 最终我们会发现,案例的耦合点由计算器类与计算类转移到命令与计算类上,可以通过接口的方式,这可以通过优化的方式来优化。
    案例github地址,如果有什么错误,欢迎指点~

参考资料:
理解设计模式之----命令模式
菜鸟教程的备忘录模式

如果想系统学习各种编程模式,菜鸟教程上的教程挺详细的~

你可能感兴趣的:(设计模式复习,编程模式,java)