这次实验主要是实现多次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. python 代码的缩进位置决定执行部分

    通过近期的代码训练,我发现同样的一个语句,在同一行缩进的位置不同,决定的执行部分也不同.先给一个例子(我想打出1-100中的前20个偶数) 比较第一张图和第二张图.第一张截图实现了我想要的功能.可是当 ...

  2. 【Canal源码分析】Canal Server的启动和停止过程

    本文主要解析下canal server的启动过程,希望能有所收获. 一.序列图 1.1 启动 1.2 停止 二.源码分析 整个server启动的过程比较复杂,看图难以理解,需要辅以文字说明. 首先程序 ...

  3. 在CentOS上装Redis

    Redis官网 $ wget http://download.redis.io/releases/redis-3.2.5.tar.gz $ tar xzf redis-.tar.gz $ cd red ...

  4. 【链表】Add Two Numbers

    题目: You are given two linked lists representing two non-negative numbers. The digits are stored in r ...

  5. Python&Appium实现安卓手机图形解锁

    首先,在解锁状态下,建立一个Session,打开APP.然后,调用press_keycode()方法传入整型数值"26",锁定屏幕.通过implicitly_wait()方法等待两 ...

  6. 机器学习--Gradient Boosting Machine(GBM)调参方法详解

    一.GBM参数 总的来说GBM的参数可以被归为三类: 树参数:调节模型中每个决策树的性质 Boosting参数:调节模型中boosting的操作 其他模型参数:调节模型总体的各项运作 1.树参数 现在 ...

  7. 业务ID 生成规则

    在实际业务中,是否碰到过这种场景: 我们需要一个单号,要在业务系统里面保证唯一,保证增长? 在运营过程,需要知道业务单发生的时间,最好不用经过系统查找就知道发生的时间? 在排障过程中,不用再次查找就知 ...

  8. java序列化测试

    0.前言 本文主要对几种常见Java序列化方式进行实现.包括Java原生以流的方法进行的序列化.Json序列化.FastJson序列化.Protobuff序列化. 1.Java原生序列化 Java原生 ...

  9. elasticSearch6源码分析(1)启动过程

    1.找到bin目录,下面有elasticSearch的sh文件,查看执行过程 exec \ "$JAVA" \ $ES_JAVA_OPTS \ -Des.path.home=&qu ...

  10. MongoDB之集合管理二

    上一博客写了集合的管理,集合里面存放的是文档,因此聪明的你应该能想到这篇是学习文档管理.要说标题应该是文档管理,不过对于文档的管理都是先获得集合对象,在集合对象上调用方法管理文档,所以标题还是对集合的 ...