这次实验主要是实现多次redo和undo,即程序的撤回和恢复,这里只实现加法的撤回和恢复。

    程序的撤回和恢复就是由所使用的软件来记录操作步骤,可以将数据恢复到某个操作状态。

    撤回这个指令很常见,Windows系统常用的快捷键ctrl+z就可以实现撤回的效果

    恢复目前只在word等文档编辑软件见到。

      

  首先说一下命令模式的结构(参考该类图,使用starUML制作):

    

    Adder类是加法的计算和返回计算后的结果, AbstrCommand是抽象类,定义三个抽象方法,AddCommand类继承AbstrCommand类,对AbstrCommand进行扩展,

  这样就可以灵活的改变命令的内容,和添加新命令。CalculatorForm类是调用AbstrCommand的方法,实现操作,并对操作的结果进行处理。通过该结构可以完成撤回和

  回复的实现。

  该结构又优点,这样设计降低了系统的耦合度,也方便加入新命令。

  接下来说一下算法实现的原理:

    首先要想撤回和恢复的实现,需要有两个栈(链表也可以),一个栈用来存储操作的每个步骤的结果,命名为撤回栈,另一个表用来

  存储撤回栈弹出的数据,命名为恢复栈。在进行加法操作的时候需要在将最新的结果压入撤回栈(保存最新操作),恢复栈清空(每次进行加法操作,

  需要清空撤回栈弹出的数据),在撤回栈的时候需要将撤回栈的栈顶弹出,并将其压入恢复栈(保存),在恢复时需要将恢复栈的栈顶弹出,并将其

  压入撤回栈,这样就完成了基本的实现,不要忘了再加上栈的空的判断。

  栈的使用:stack<Object>  stack = new Stack<Object>();    定义 (说明类型)

       Object j=stack.peek();   返回栈顶元素的值

       Object j=stack.pop();    弹出栈顶元素的值,j是弹出的值

       Object j=stack.push(Object element);    将值压入栈

  源代码:

  //实现加法的计算和返回计算的值

  

 public class Adder {
private int num =0;
public int add(int value) {
num+=value;
return num;
}
}

Adder类

  //抽象命令类

  

 public abstract class AbstractCommand {
public abstract int execute(int value); public abstract int undo(); public abstract int redo();
}

AbstractCommand 类

 //加法命令类

  

 import java.util.Stack;

 public class AddCommand extends AbstractCommand {
private Adder adder = new Adder();
private Stack<Integer> unStack = new Stack<Integer>();// 返回栈,用来记录所做的每一步操作,用于撤回
private Stack<Integer> reStack = new Stack<Integer>();// 重复栈,用来存储返回栈弹出的数据,由于重复 /**
* 撤回
*/
public int undo() {
int i=0;
if (unStack.isEmpty()) { i=-1;
}else{
Integer pop = unStack.pop();
reStack.push(pop);
if(!unStack.isEmpty()){//判断弹出数据后是否为空,如果为空,说明已撤回到最原始状态
i=unStack.peek();
}
}
return i;
} /**
* 恢复
*/
public int redo() {
int i=0;
if (reStack.isEmpty()) {
i=-1;
}else{//撤回时只要可以可以撤回,则返回栈一定有数据
Integer pop = reStack.pop();
unStack.push(pop);
i=pop;
}
return i;
} /**
* 执行计算,并进行栈的更新
*/
public int execute(int value) {
int v = 0;
if (unStack.isEmpty()) {// 说明还没有数据
v = adder.add(value);
unStack.push(v);
} else {// 需要更新两个栈中的内容,并计算结果,其中返回栈应该更新,重复栈应该清空
v = adder.add(value);
unStack.push(v);
if (!reStack.isEmpty()) {
for (int i = 0; i < reStack.size(); i++) {
reStack.pop();
}
}
}
return v;
}
}

AddCommand类

  

 public class CalculatorForm {
private AbstractCommand command;
public void setCommand(AbstractCommand command) {
this.command =command;
}
/**
* 执行运算
* @param value
*/
public void compute(int value) {
command.execute(value);
}
/**
* 撤回
*/
public void undo() {
int i = command.undo();
if(i==-1){
System.out.println("缓存中已不存在数据");
}else{
System.out.println("执行成功,运算结果是:"+i);
}
}
/**
* 恢复
*/
public void redo() {
int i = command.redo();
if(i==-1){
System.out.println("已恢复至最新数据");
}
else{
System.out.println("执行成功,运算结果是:"+i);
}
}
}

CalculatorForm(引用命令)类

  //测试结果

  

 public class client {
public static void main(String[] args) {
CalculatorForm form = new CalculatorForm();
AddCommand command = new AddCommand();
form.setCommand(command);
//计算
System.out.println("------计算过程-----");
form.compute(1);
form.compute(2);
form.compute(3);
form.compute(4);
//多次撤回
System.out.println("------撤回过程-----");
form.undo();
form.undo();
form.undo();
form.undo();
form.undo();
//多次恢复
System.out.println("------恢复过程-----");
form.redo();
form.redo();
form.redo();
form.redo();
form.redo();
}
}

client 类

  实验总结:

    通过本次试验,对命令模式有了基本了解,命令模式很容易实现undo和redo,在本次试验我使用了stack栈用来实现多次的撤回和恢复,透彻理解使用两个栈,用来对数据

进行恢复的原理,就可以很快的解决该问题。

命令模式-实现undo和redo的更多相关文章

  1. 从Undo,Redo谈命令模式

    一般的应用软件中,通常会提供Redo和Undo的操作,比如Paint.NET中的动作面板,Word中的撤销重做,一般我们按Ctrl-Z即可回退到上次操作. 要实现上面的这一功能,最直观的想法就是,我们 ...

  2. 设计模式 - 命令模式(command pattern) 撤销(undo) 具体解释

    命令模式(command pattern) 撤销(undo) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.cs ...

  3. [Head First设计模式]餐馆中的设计模式——命令模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  4. c#设计模式-命令模式

    一. 命令(Command)模式 命令(Command)模式属于对象的行为模式[GOF95].命令模式又称为行动(Action)模式或交易(Transaction)模式.命令模式把一个请求或者操作封装 ...

  5. 15.命令模式(Command Pattern)

    using System; namespace ConsoleApplication8 { class Program { /// <summary> /// 在软件系统中,“行为请求者” ...

  6. 深入浅出设计模式——命令模式(Command Pattern)

    模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请 ...

  7. C#设计模式(15)——命令模式(Command Pattern)

    一.前言 之前一直在忙于工作上的事情,关于设计模式系列一直没更新,最近项目中发现,对于设计模式的了解是必不可少的,当然对于设计模式的应用那更是重要,可以说是否懂得应用设计模式在项目中是衡量一个程序员的 ...

  8. 大熊君说说JS与设计模式之------命令模式Command

    一,总体概要 1,笔者浅谈 日常生活中,我们在看电视的时候,通过遥控器选择我们喜欢的频道时,此时我们就是客户端的角色,遥控器的按钮相当于客户请求,而具体执行的对象就是命令对象, 命令模式把一个请求或者 ...

  9. 设计模式:命令模式(Command)

    定   义:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排列或者记录请求日志,以及支持可撤销的操作. 结构图: Command类: abstract class Comma ...

随机推荐

  1. paddlepaddle使用(一)

    paddlepaddle是百度提出来的深度学习的框架,个人感觉其实和tensorflow差不多(语法上面),因为本人也是初学者,也不是很懂tensorflow,所以,这些都是个人观点. 百度的padd ...

  2. 过虑器应用之1-设置request编码

    一:设置Post编码 post请求接收中文,需要在Servlet里写上 request.setCharacterEncoding("UTF-8"); 否则默认以iso-8859-1 ...

  3. 关于Class中的Signature属性

    1.Signature属性:https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.9 2.ClassSigna ...

  4. Python函数中的可变参数

    在Python函数中,还可以定义可变参数. 如:给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……. 要定义出这个函数,我们必须确定输入的参数.由于参数个数不确定,我们首先想到可以把 ...

  5. mongodb limit()和skip()

    MongoDB Limit() 方法 如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的 ...

  6. redis实战笔记(7)-第7章 基于搜索的应用程序

    本章主要内容   使用Redis进行搜索 对搜索结果进行排序 实现广告定向 实现职位搜索    

  7. python算法之冒泡排序

    目录 python之冒泡排序 算法原理 算法分析 代码实现 总结 python之冒泡排序 概念: 重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小.首字母从A到Z)错误就 ...

  8. rabbitmq不同模式的交换机使用

    交换机的功能主要是接收消息并且转发到绑定的队列,交换机不存储消息,在启用ack模式后,交换机找不到队列会返回错误.交换机有四种类型:Direct, topic, Headers and Fanout( ...

  9. 添加右键使用 SublimeText 打开

    最近修改了系统,重新安装 SublimeText 但是在安装的时候忘记设置右键使用 SublimeText 打开,所以就需要写注册表. 可以复制下面的代码到一个记事本,然后保存为 sublime_ad ...

  10. 商城项目,java返回json数据,报错406

    前言: 项目结构为maven,搭建好架构,整合ssm,进行测试, 从数据库中查询数据,返回json数据,结果报错406 问题: 解决: 1,确定项目中json包是否存在(极大可能出于此) 2,处理器适 ...