命令模式-实现undo和redo

 这次实验主要是实现多次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);    将值压入栈

  源代码:

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

  

1 public class Adder {
2     private int num =0;
3     public int add(int value) {
4         num+=value;
5         return num;
6     }
7 }

Adder类

  //抽象命令类

  

1 public abstract class AbstractCommand {
2     public abstract int execute(int value);
3
4     public abstract int undo();
5
6     public abstract int redo();
7 }

AbstractCommand 类

 //加法命令类

  

 1 import java.util.Stack;
 2
 3
 4
 5 public class AddCommand extends AbstractCommand {
 6     private Adder adder = new Adder();
 7     private Stack<Integer> unStack = new Stack<Integer>();// 返回栈,用来记录所做的每一步操作,用于撤回
 8     private Stack<Integer> reStack = new Stack<Integer>();// 重复栈,用来存储返回栈弹出的数据,由于重复
 9
10     /**
11      * 撤回
12      */
13     public int undo() {
14         int i=0;
15         if (unStack.isEmpty()) {
16
17             i=-1;
18         }else{
19             Integer pop = unStack.pop();
20             reStack.push(pop);
21             if(!unStack.isEmpty()){//判断弹出数据后是否为空,如果为空,说明已撤回到最原始状态
22                 i=unStack.peek();
23             }
24         }
25         return i;
26     }
27
28     /**
29      * 恢复
30      */
31     public int redo() {
32         int i=0;
33         if (reStack.isEmpty()) {
34             i=-1;
35         }else{//撤回时只要可以可以撤回,则返回栈一定有数据
36             Integer pop = reStack.pop();
37             unStack.push(pop);
38             i=pop;
39         }
40         return i;
41     }
42
43     /**
44      * 执行计算,并进行栈的更新
45      */
46     public int execute(int value) {
47         int v = 0;
48         if (unStack.isEmpty()) {// 说明还没有数据
49             v = adder.add(value);
50             unStack.push(v);
51         } else {// 需要更新两个栈中的内容,并计算结果,其中返回栈应该更新,重复栈应该清空
52             v = adder.add(value);
53             unStack.push(v);
54             if (!reStack.isEmpty()) {
55                 for (int i = 0; i < reStack.size(); i++) {
56                     reStack.pop();
57                 }
58             }
59         }
60         return v;
61     }
62 }

AddCommand类

  

 1 public class CalculatorForm {
 2     private AbstractCommand command;
 3     public void setCommand(AbstractCommand command) {
 4         this.command =command;
 5     }
 6     /**
 7      * 执行运算
 8      * @param value
 9      */
10     public void compute(int value) {
11         command.execute(value);
12     }
13     /**
14      * 撤回
15      */
16     public void undo() {
17         int i = command.undo();
18         if(i==-1){
19             System.out.println("缓存中已不存在数据");
20         }else{
21             System.out.println("执行成功,运算结果是:"+i);
22         }
23     }
24     /**
25      * 恢复
26      */
27     public void redo() {
28          int i = command.redo();
29         if(i==-1){
30             System.out.println("已恢复至最新数据");
31         }
32         else{
33             System.out.println("执行成功,运算结果是:"+i);
34         }
35     }
36 }

CalculatorForm(引用命令)类

  //测试结果

  

 1 public class client {
 2     public static void main(String[] args) {
 3         CalculatorForm form = new CalculatorForm();
 4         AddCommand command = new AddCommand();
 5         form.setCommand(command);
 6         //计算
 7         System.out.println("------计算过程-----");
 8         form.compute(1);
 9         form.compute(2);
10         form.compute(3);
11         form.compute(4);
12         //多次撤回
13         System.out.println("------撤回过程-----");
14         form.undo();
15         form.undo();
16         form.undo();
17         form.undo();
18         form.undo();
19         //多次恢复
20         System.out.println("------恢复过程-----");
21         form.redo();
22         form.redo();
23         form.redo();
24         form.redo();
25         form.redo();
26     }
27 }

client 类

  实验总结:

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

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

时间: 2024-10-11 21:03:29

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

使用备忘录模式实现Undo和Redo

备忘录模式有三个角色.1.发起人(Originator)角色:负责创建一个备忘录,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态.实现其他业务功能.2.备忘录(Memento)角色:负责存储发起人的内部状态.3.管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改. /** * 发起人角色 * */ public class UnRedoOriginator { private String state; public

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

命令模式(command pattern) 撤销(undo) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.csdn.net/caroline_wendy/article/details/31379977 命令模式能够用于运行撤销(undo)操作. 详细方法: 1. 对象类中须要保存状态, 如level. package command; public class CeilingFan { String lo

设计模式 - 命令模式(command pattern) 撤销(undo) 详解

命令模式(command pattern) 撤销(undo) 详解 本文地址: http://blog.csdn.net/caroline_wendy 参考命令模式: http://blog.csdn.net/caroline_wendy/article/details/31379977 命令模式可以用于执行撤销(undo)操作. 具体方法: 1. 对象类中需要保存状态, 如level. package command; public class CeilingFan { String loca

设计模式完结(14)-- 命令模式 --- 请求发送者与接收者解耦

起连接作用:  类似开关   和  电器  之间的   电线 请求发送者与接收者解耦,  引入命令类 abstract class Command { public abstract void execute(); } class Invoker { private Command command; //构造注入 public Invoker(Command command) { this.command = command; } //设值注入 public void setCommand(Co

ctrl+z的JAVA实现,借助了命令模式(command pattern)

前些天学习<<JAVA与模式>>,到命令模式时,随带给了一个CTRL+Z案例的实现,想来学习编程这么久,CTRL+Z还没有认真实现过. 因此,借助JAVA与模式里面的源代码,自己对撤销和回退进行了实现(JAVA与模式书中代码有部分问题).此次用到了命令模式,因为有界面,有按钮,有接收者,有发送者. 以下是类图,只为方便,未考虑UML细节规范. 以下是程序的实现. MainFrame类:提供Main方法,Client类:类似于看电视的人,这里关联了UndoableTextArea,I

【设计模式】—— 命令模式Commond

前言:[模式总览]——————————by xingoo 模式意图 将一个请求封装成一个对象,从而对这个命令执行撤销.重做等操作. 典型的Eclipse开发中,编辑器的操作就需要用到这个模式,比如Undo.Redo等等. 另外这个模式使得一个命令的触发与接收解耦,这样我们就可以演变成把感兴趣的对象接收这个命令,当命令触发时,这些对象就会执行操作.这个机制也是java事件的处理方式. 应用场景 1 命令抽象成对象 2 在不同的时刻,指定或者排队命令 3 支持 Undo或者Redo等操作 4 修改日

设计模式14:Command 命令模式(行为型模式)

Command 命令模式(行为型模式) 耦合与变化 耦合是软件不能抵御变化的根本性原因.不仅实体对象与实体对象之间存在耦合关系,实体对象与行为操作之间也存在耦合关系. 动机(Motivation) 在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”.但在某些场合——比如对行为进行“记录.撤销/重做(undo/redo).事务”等处理,这种无法抵御变化的紧耦合是不合适的. 在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,可以实现二者之间的解耦. 意

PHP设计模式——命令模式

声明:本系列博客参考资料<大话设计模式>,作者程杰. 命令模式:在软件系统中,"行为请求者"与"行为实现者"通常呈现一种"紧耦合".但在某些场合,比如要对行为进行"记录.撤销/重做.事务"等处理,这种无法抵御变化的紧耦合是不合适的.在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,实现二者之间的松耦合.这就是命令模式. 类图: 角色分析: 抽象命令

设计模式学习笔记之命令模式

命令模式 将“请求”封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 说明: 1.命令模式将发出请求的对象和执行请求的对象解耦: 2.在被解耦的两者之间是通过命令对象进行沟通的.命令对象封装了接受者和一个或一组动作: 3.调用者通过调用命令对象的execute()发出请求,这会使得接受者的动作被调用: 4.调用者可以接受命令当做参数,甚至在运行时动态地进行: 5.命令可以支持撤销,做法事实现一个undo()方法来回到exexcute()被执行前的状态: