5 撤销操作的实现

在命令模式中,我们可以通过调用一个命令对象的execute()方法来实现对请求的处理,如果需要撤销(Undo)请求,可通过在命令类中增加一个逆向操作来实现。

扩展

除了通过一个逆向操作来实现撤销(Undo)外,还可以通过保存对象的历史状态来实现撤销,后者可使用备忘录模式(Memento Pattern)来实现。

下面通过一个简单的实例来学习如何使用命令模式实现撤销操作:

Sunny软件公司欲开发一个简易计算器,该计算器可以实现简单的数学运算,还可以对运算实施撤销操作。

Sunny软件公司开发人员使用命令模式设计了如图5所示结构图,其中计算器界面类CalculatorForm充当请求发送者,实现了数据求和功能的加法类Adder充当请求接收者,界面类可间接调用加法类中的add()方法实现加法运算,并且提供了可撤销加法运算的undo()方法。

图5  简易计算器结构图

本实例完整代码如下所示:

[java]view plain copy
  1. //加法类:请求接收者
  2. class Adder {
  3. private int num=0; //定义初始值为0
  4. //加法操作,每次将传入的值与num作加法运算,再将结果返回
  5. public int add(int value) {
  6. num += value;
  7. return num;
  8. }
  9. }
  10. //抽象命令类
  11. abstract class AbstractCommand {
  12. public abstract int execute(int value); //声明命令执行方法execute()
  13. public abstract int undo(); //声明撤销方法undo()
  14. }
  15. //具体命令类
  16. class ConcreteCommand extends AbstractCommand {
  17. private Adder adder = new Adder();
  18. private int value;
  19. //实现抽象命令类中声明的execute()方法,调用加法类的加法操作
  20. public int execute(int value) {
  21. this.value=value;
  22. return adder.add(value);
  23. }
  24. //实现抽象命令类中声明的undo()方法,通过加一个相反数来实现加法的逆向操作
  25. public int undo() {
  26. return adder.add(-value);
  27. }
  28. }
  29. //计算器界面类:请求发送者
  30. class CalculatorForm {
  31. private AbstractCommand command;
  32. public void setCommand(AbstractCommand command) {
  33. this.command = command;
  34. }
  35. //调用命令对象的execute()方法执行运算
  36. public void compute(int value) {
  37. int i = command.execute(value);
  38. System.out.println("执行运算,运算结果为:" + i);
  39. }
  40. //调用命令对象的undo()方法执行撤销
  41. public void undo() {
  42. int i = command.undo();
  43. System.out.println("执行撤销,运算结果为:" + i);
  44. }
  45. }

编写如下客户端测试代码:

[java]view plain copy
  1. class Client {
  2. public static void main(String args[]) {
  3. CalculatorForm form = new CalculatorForm();
  4. AbstractCommand command;
  5. command = new ConcreteCommand();
  6. form.setCommand(command); //向发送者注入命令对象
  7. form.compute(10);
  8. form.compute(5);
  9. form.compute(10);
  10. form.undo();
  11. }
  12. }

编译并运行程序,输出结果如下:

执行运算,运算结果为:10

执行运算,运算结果为:15

执行运算,运算结果为:25

执行撤销,运算结果为:15

思考

如果连续调用“form.undo()”两次,预测客户端代码的输出结果。

需要注意的是在本实例中只能实现一步撤销操作,因为没有保存命令对象的历史状态,可以通过引入一个命令集合或其他方式来存储每一次操作时命令的状态,从而实现多次撤销操作。除了Undo操作外,还可以采用类似的方式实现恢复(Redo)操作,即恢复所撤销的操作(或称为二次撤销)。

练习

修改简易计算器源代码,使之能够实现多次撤销(Undo)和恢复(Redo)。

【作者:刘伟   http://blog.csdn.net/lovelion】

请求发送者与接收者解耦——命令模式(四)相关推荐

  1. 请求发送者与接收者解耦——命令模式

    本文转载自 :http://blog.csdn.net/lovelion/article/details/8796736 装修新房的最后几道工序之一是安装插座和开关,通过开关可以控制一些电器的打开和关 ...

  2. 广播发送者广播接收者介绍

    1.广播接收者 广播接收者简单地说就是接收广播意图的Java类,此Java类继承BroadcastReceiver类,重写: public void onReceive(Context context ...

  3. Boost:基于Boost的发送者和接收者的测试程序

    Boost:基于Boost的发送者和接收者的测试程序 实现功能 C++实现代码 发送者源码 接收者源码 实现功能 基于Boost的发送者和接收者的测试程序 C++实现代码 发送者源码 #include ...

  4. 16、设计模式-行为型模式-命令模式

    命令模式(请求发送者与接收者解耦) 在软件开发中,我们经常需要向某些对象发送请求(调用其中的某个或某些方法),但是并 不知道请求的接收者是谁,也不知道被请求的操作是哪个,此时,我们特别希望能够以一种 ...

  5. [C++设计模式] command 命令模式

    在软件系统中,"行为请求者"与"行为实现者"通常呈现一种"紧耦合". 但在某些场合,比方要对行为进行"记录.撤销/重做.事务&qu ...

  6. Activiti 中的 命令模式与责任链模式

    Activiti 中的 命令模式与责任链模式 类图: 标准命令模式: 意图:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化. 主要解决:在软件系统中,行为请求者与行为实现者通常是一 ...

  7. 设计模式之命令模式详解

    1 概述 日常生活中,我们出去吃饭都会遇到下面的场景.我们可以将女招待理解成一个请求的发送者,用户通过它来发送一个"点餐"请求,而厨师是"点餐"请求的最终接收者 ...

  8. 设计模式之命令模式详解(附应用举例实现)

    文章目录 1 命令模式介绍 2 命令模式详解 2.1 命令模式结构 2.2 命令模式实现 2.3 命令模式应用举例 3 实现命令队列 1 命令模式介绍 在现实生活中人们通过使用开关来控制一些电器的打开 ...

  9. 设计模式笔记:命令模式

    首先看看命令模式的定义:命令模式将请求封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持撤销的操作. 所谓参数化,我的理解是实际执行的对象,比如light(电灯).strer ...

  10. 3.4 命令模式(5.2)

    1. 引子 假定电视机/TV有方法open().close()和changeChannel()用于打开.关闭和切换电视频道,而遥控器/Controller对TV的操作,通常使用消息传递/方法调用表达式 ...

最新文章

  1. oracle为什么不用指定数据库,两个数据库怎么保持数据正确显示
  2. Java与JS代码调试技巧
  3. 京东某员工因加班太多引女友不满,下定决心离职:不想被迫加班!
  4. Vue指令v-for之遍历输出JavaScript数组,json对象的几种方式
  5. 第四周项目五-用递归方法求解(求1*3*5*...*n的递归式)
  6. 图像PSNR值及MSE值的计算
  7. c语言程序设计k.r,【答题】C语言程序设计问题与解释实验
  8. php里push的用法,php array_push函数怎么用?
  9. 需求、需求工程与需求工程师 — 2.需求的来源
  10. NYOJ----1591----模拟+map
  11. 锋利的jQuery(汇总)
  12. 【业务人员第一视角】氚云低代码开发平台测评
  13. java文本框背景_Java 添加文本框到PPT幻灯片过程解析
  14. 利用python实现对豆瓣排名电影的信息获取
  15. 微信公众账号数据交互图
  16. 一个牛人在美国的跳槽经历(转)
  17. SpringBoot (八)日志配置
  18. HDU - 4598 Difference
  19. VisionPro相机操作类
  20. Linux--自旋锁(介绍及API简介)

热门文章

  1. hdu 2642 Stars 树状数组
  2. 15个非常有用的Adobe Flex教程
  3. sql server连接字符串
  4. 有趣的东西:Test () () () () () () () () () ();
  5. java json 本身_JSON以及Java转换JSON的方法(前后端常用处理方法)
  6. swift. 扩展类添加属性_swift 扩展属性的方法
  7. centos7 安装mysql_第02期:ClickHouse 单机部署以及从 MySQL 增量同步数据
  8. python画图代码讲解_python画图例子代码
  9. Yarn的原理与资源调度
  10. 23种设计模式的意图和适用范围