一、命令模式定义

命令大家都不会陌生,那么在开始命令模式之前,可以想象一下生活中的命令模式的特点:

如老板命令你完成一个OA项目是一个命令,接着看看其特点:

1、在上面的命令中,命令的执行者肯定是聪明的你了。具体的执行方法,可能是通过vs实现,或者是通过eclipse实现,由此看来:命令要有个命令的执行者,还要有个命令的执行方法。

2、命令的发出者很明显是老板,老板还有个发出方法,可能是通过电话给你说,也可能给你邮件给你说,也可能是通过开会给你说。所以命令的发出者要有一个命令,还要有个发出的方法。

3、最后看看命令,命令有个名字,命令的肯定要执行。而且命令是在boss给你发出通知后执行的。

接下来看看命令模式的定义:

命令模式:将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。

二、问题描述

使用命令模式实现遥控器,遥控器上的不同按钮控制电灯的开关及亮度、天花板风扇的开关及转速等,支持撤销。具体按钮:开灯/关灯按钮、暗光开/关按钮、风扇高速/中速/低速/关按钮、撤销按钮。遥控器如下图所示:

遥控器担当请求者(或称为调用者)的角色,用RemoteControlWithUndo类实现,其内有Command[]类型的属性onCommands和offCommands表示对应的一组开关,Command类型的属性undoCommand记录最后执行的命令用于命令的撤销。遥控器上有7组开关按钮和一个撤销按钮。每个按钮对应一个具体命令,说明如下:

三、类图

四、代码实现

1.命令角色:Command

  1. public interface Command {
  2. public void execute();
  3. public void undo();//实现撤销
  4. }

2.接收者角色:Light、CeilingFan

(1)Light电灯:

  1. public class Light {
  2. String location;
  3. int level;//灯光的亮度
  4. public Light(String location) {
  5. this.location = location;
  6. }
  7. public void on() {
  8. level = 100;
  9. System.out.println("Light is on");
  10. }
  11. public void off() {
  12. level = 0;
  13. System.out.println("Light is off");
  14. }
  15. //调整灯光的亮度
  16. public void dim(int level) {
  17. this.level = level;
  18. if (level == 0) {
  19. off();
  20. }
  21. else {
  22. System.out.println("Light is dimmed to " + level + "%");
  23. }
  24. }
  25. //获取灯光的亮度
  26. public int getLevel() {
  27. return level;
  28. }
  29. }

(2)CeilingFan风扇:

  1. public class CeilingFan {
  2. public static final int HIGH = 3;
  3. public static final int MEDIUM = 2;
  4. public static final int LOW = 1;
  5. public static final int OFF = 0;
  6. String location;//例如卧室、客厅的风扇?
  7. int speed;
  8. public CeilingFan(String location) {
  9. this.location = location;
  10. speed = OFF;
  11. }
  12. public void high() {
  13. speed = HIGH;
  14. System.out.println(location + " ceiling fan is on high");
  15. }
  16. public void medium() {
  17. speed = MEDIUM;
  18. System.out.println(location + " ceiling fan is on medium");
  19. }
  20. public void low() {
  21. speed = LOW;
  22. System.out.println(location + " ceiling fan is on low");
  23. }
  24. public void off() {
  25. speed = OFF;
  26. System.out.println(location + " ceiling fan is off");
  27. }
  28. public int getSpeed() {
  29. return speed;
  30. }
  31. }

3.具体命令角色:各种命令

(1)NoCommand:空命令,创建遥控器时默认其持有的都是空命令(相比判断null更好),什么事也不做

  1. public class NoCommand implements Command {
  2. public void execute() { }
  3. public void undo() { }
  4. }

(2)LightOnCommand:开灯命令

  1. public class LightOnCommand implements Command {
  2. Light light;
  3. int level;//level用于记录上次的灯光亮度
  4. public LightOnCommand(Light light) {
  5. this.light = light;
  6. }
  7. public void execute() {
  8. level = light.getLevel();
  9. light.on();
  10. }
  11. public void undo() {//将灯光的亮度调到前一次的水平实现撤销
  12. light.dim(level);
  13. }
  14. }

(3)LightOffCommand:关灯命令

  1. public class LightOffCommand implements Command {
  2. Light light;
  3. int level;
  4. public LightOffCommand(Light light) {
  5. this.light = light;
  6. }
  7. public void execute() {
  8. level = light.getLevel();
  9. light.off();
  10. }
  11. public void undo() {
  12. light.dim(level);
  13. }
  14. }

(4)DimmerLightOnCommand:开启暗光

  1. public class DimmerLightOnCommand implements Command {
  2. Light light;
  3. int prevLevel;//记录以前的灯光亮度,撤销操作时使用
  4. public DimmerLightOnCommand(Light light) {
  5. this.light = light;
  6. }
  7. public void execute() {
  8. prevLevel = light.getLevel();
  9. light.dim(75);//将灯光亮度调至75%实现暗光
  10. }
  11. public void undo() {
  12. light.dim(prevLevel);
  13. }
  14. }

(5)DimmerLightOffCommand:关闭暗光

  1. public class DimmerLightOffCommand implements Command {
  2. Light light;
  3. int prevLevel;
  4. public DimmerLightOffCommand(Light light) {
  5. this.light = light;
  6. prevLevel = 100;
  7. }
  8. public void execute() {
  9. prevLevel = light.getLevel();
  10. light.off();
  11. }
  12. public void undo() {
  13. light.dim(prevLevel);
  14. }
  15. }

(6)CeilingFanHighCommand:风扇高转速

  1. public class CeilingFanHighCommand implements Command {
  2. CeilingFan ceilingFan;
  3. int prevSpeed;//记录以前的转速,用于撤销操作(0时表示以前的状态是:关)
  4. public CeilingFanHighCommand(CeilingFan ceilingFan) {
  5. this.ceilingFan = ceilingFan;
  6. }
  7. public void execute() {
  8. prevSpeed = ceilingFan.getSpeed();
  9. ceilingFan.high();
  10. }
  11. public void undo() {
  12. if (prevSpeed == CeilingFan.HIGH) {
  13. ceilingFan.high();
  14. } else if (prevSpeed == CeilingFan.MEDIUM) {
  15. ceilingFan.medium();
  16. } else if (prevSpeed == CeilingFan.LOW) {
  17. ceilingFan.low();
  18. } else if (prevSpeed == CeilingFan.OFF) {
  19. ceilingFan.off();
  20. }
  21. }
  22. }

(7)CeilingFanMediumCommand:风扇中转速

  1. public class CeilingFanMediumCommand implements Command {
  2. CeilingFan ceilingFan;
  3. int prevSpeed;
  4. public CeilingFanMediumCommand(CeilingFan ceilingFan) {
  5. this.ceilingFan = ceilingFan;
  6. }
  7. public void execute() {
  8. prevSpeed = ceilingFan.getSpeed();
  9. ceilingFan.medium();//将行为的真正执行委托给接收者,此处即ceilingFan风扇对象
  10. }
  11. public void undo() {
  12. if (prevSpeed == CeilingFan.HIGH) {
  13. ceilingFan.high();
  14. } else if (prevSpeed == CeilingFan.MEDIUM) {
  15. ceilingFan.medium();
  16. } else if (prevSpeed == CeilingFan.LOW) {
  17. ceilingFan.low();
  18. } else if (prevSpeed == CeilingFan.OFF) {
  19. ceilingFan.off();
  20. }
  21. }
  22. }

(8)CeilingFanLowCommand:风扇低转速

  1. public class CeilingFanLowCommand implements Command {
  2. CeilingFan ceilingFan;
  3. int prevSpeed;
  4. public CeilingFanLowCommand(CeilingFan ceilingFan) {
  5. this.ceilingFan = ceilingFan;
  6. }
  7. public void execute() {
  8. prevSpeed = ceilingFan.getSpeed();
  9. ceilingFan.low();
  10. }
  11. public void undo() {
  12. if (prevSpeed == CeilingFan.HIGH) {
  13. ceilingFan.high();
  14. } else if (prevSpeed == CeilingFan.MEDIUM) {
  15. ceilingFan.medium();
  16. } else if (prevSpeed == CeilingFan.LOW) {
  17. ceilingFan.low();
  18. } else if (prevSpeed == CeilingFan.OFF) {
  19. ceilingFan.off();
  20. }
  21. }
  22. }

(9)CeilingFanOffCommand:关闭风扇

  1. public class CeilingFanOffCommand implements Command {
  2. CeilingFan ceilingFan;
  3. int prevSpeed;
  4. public CeilingFanOffCommand(CeilingFan ceilingFan) {
  5. this.ceilingFan = ceilingFan;
  6. }
  7. public void execute() {
  8. prevSpeed = ceilingFan.getSpeed();
  9. ceilingFan.off();
  10. }
  11. public void undo() {
  12. if (prevSpeed == CeilingFan.HIGH) {
  13. ceilingFan.high();
  14. } else if (prevSpeed == CeilingFan.MEDIUM) {
  15. ceilingFan.medium();
  16. } else if (prevSpeed == CeilingFan.LOW) {
  17. ceilingFan.low();
  18. } else if (prevSpeed == CeilingFan.OFF) {
  19. ceilingFan.off();
  20. }
  21. }
  22. }

4.遥控器类,请求者(或调用者)角色,持有多个Command对象

  1. public class RemoteControlWithUndo {
  2. Command[] onCommands;//对应多个开按钮
  3. Command[] offCommands;//对应多个关按钮
  4. Command undoCommand;//对应撤销按钮
  5. public RemoteControlWithUndo() {
  6. onCommands = new Command[7];
  7. offCommands = new Command[7];
  8. Command noCommand = new NoCommand();
  9. for(int i=0;i<7;i++) {
  10. onCommands[i] = noCommand;//默认赋值为空命令,什么事也不做
  11. offCommands[i] = noCommand;
  12. }
  13. undoCommand = noCommand;
  14. }
  15. public void setCommand(int slot, Command onCommand, Command offCommand) {
  16. onCommands[slot] = onCommand;
  17. offCommands[slot] = offCommand;
  18. }
  19. //当编号为第slot的开On按钮按下时执行命令
  20. public void onButtonWasPushed(int slot) {
  21. onCommands[slot].execute();
  22. undoCommand = onCommands[slot];//记录最后执行的命令
  23. }
  24. public void offButtonWasPushed(int slot) {
  25. offCommands[slot].execute();
  26. undoCommand = offCommands[slot];
  27. }
  28. public void undoButtonWasPushed() {
  29. undoCommand.undo();
  30. }
  31. public String toString() {
  32. StringBuffer stringBuff = new StringBuffer();
  33. stringBuff.append("\n------ Remote Control -------\n");
  34. for (int i = 0; i < onCommands.length; i++) {
  35. stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()
  36. + "    " + offCommands[i].getClass().getName() + "\n");
  37. }
  38. stringBuff.append("[undo] " + undoCommand.getClass().getName() + "\n");
  39. return stringBuff.toString();
  40. }
  41. }

5.测试

  1. public class RemoteLoader {
  2. public static void main(String[] args) {
  3. RemoteControlWithUndo remoteControl = new RemoteControlWithUndo();
  4. Light livingRoomLight = new Light("Living Room");
  5. LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
  6. LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
  7. DimmerLightOnCommand dimmerLightOnCommand=new DimmerLightOnCommand(livingRoomLight);
  8. DimmerLightOffCommand dimmerLightOffCommand=new DimmerLightOffCommand(livingRoomLight);
  9. CeilingFan ceilingFan = new CeilingFan("Living Room");
  10. CeilingFanHighCommand ceilingFanHigh = new CeilingFanHighCommand(ceilingFan);
  11. CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);
  12. CeilingFanLowCommand ceilingFanLow =new CeilingFanLowCommand(ceilingFan);
  13. CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
  14. remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
  15. remoteControl.setCommand(1, dimmerLightOnCommand, dimmerLightOffCommand);
  16. remoteControl.setCommand(2, ceilingFanHigh, ceilingFanOff);
  17. remoteControl.setCommand(3, ceilingFanMedium, ceilingFanOff);
  18. remoteControl.setCommand(4, ceilingFanLow, ceilingFanOff);
  19. remoteControl.onButtonWasPushed(1);
  20. remoteControl.onButtonWasPushed(3);
  21. remoteControl.onButtonWasPushed(2);
  22. remoteControl.offButtonWasPushed(3);
  23. remoteControl.undoButtonWasPushed();
  24. }
  25. }

运行结果:

  1. Light is dimmed to 75%
  2. Living Room ceiling fan is on medium
  3. Living Room ceiling fan is on high
  4. Living Room ceiling fan is off
  5. Living Room ceiling fan is on high

我们可以很轻松地利用组合模式加入宏命令,还有,正如以上代码所示,命令模式的不足之处就是我们需要维护大量的具体命令类。

转载于:https://my.oschina.net/u/3088173/blog/1021776

《设计模式》之命令模式相关推荐

  1. java命令_JAVA与模式之命令模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述命令(Command)模式的: 命令模式属于对象的行为模式.命令模式又称为行动(Action)模式或交易(Transaction)模式. ...

  2. 图解Java设计模式学习笔记——行为型模式(模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式)

    一.模板方法模式(模板模式)--钩子方法 1.需求-豆浆制作问题 编写制作豆浆的程序,说明如下: 制作豆浆的流程选材-->添加配料-->浸泡-->放到豆浆机打碎. 通过添加不同的配料 ...

  3. IOS设计模式之四(备忘录模式,命令模式)

    本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq) ...

  4. 设计模式(模板模式,命令模式,备忘录模式)

    目录 模板模式 什么是模板模式? 术语? 什么时候使用模板模式? 模板模式的优点? 模板模式的缺点? 角色? 钩子函数? 注意事项和细节? 什么场景使用模板模式? 案例: 命令模式 什么是命令模式? ...

  5. 行为型模式:命令模式

    LieBrother原文: 行为型模式:命令模式 十一大行为型模式之三:命令模式. 简介 姓名 :命令模式 英文名 :Command Pattern 价值观 :军令如山 个人介绍 : Encapsul ...

  6. 详解Linux系统Vi 和 Vim中正常模式、编辑模式、命令模式相互转化,以及vim命令使用

    详解Linux系统Vi 和 Vim中正常模式.编辑模式.命令模式相互转化 vi 和 vim 的基本介绍 vi 和 vim 的三种常见模式 正常模式 正常模式常用命令 插入模式/编辑模式 命令行模式 v ...

  7. 设计模式之模板方法模式、策略模式、命令模式、责任链模式、状态模式

    前言 本章节给您介绍23种设计模式的行为型模式中的模板方法模式.策略模式.命令模式.责任链模式.状态模式. 如有帮助记得3连 加 关注哦!欢迎品论去留言交流,谢谢阅读! 文章目录 前言 一.模板方法模 ...

  8. 通过英雄联盟塞拉斯大招学习策略模式和命令模式

    通过英雄联盟塞拉斯大招学习策略模式和命令模式 前段时间学习了策略模式,第一时间我就想到了英雄联盟当中的英雄塞拉斯,塞拉斯的大招是整个联盟最特殊的大招之一,他可以偷取别的英雄的大招.后面又学习到了命令模 ...

  9. java execute 执行成功_【JAVA】设计模式之命令模式(Command模式)的使用分析

    命令模式属于23种设计模式中行为模式中的一个,它也是一种简单实用非常普遍的设计模式. 首先看下GOF对命令模式的定义:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录 ...

  10. Java设计模式学习总结(16)——行为型模式之命令模式

    命令模式 命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式.请求以命令的形式包裹在对象中,并传给调用对象.调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应 ...

最新文章

  1. 分布式主键解决方案----Twitter 雪花算法的原理(Java 版)
  2. GMap.net 离线地图问题
  3. 编程珠玑第八章——分治算法求解数组中的最大的连续和
  4. 03-CoreData原理
  5. wxWidgets:wxSplitterWindow类用法
  6. .NET或将引入类型类和扩展
  7. oauth2.0 php简化模式,OAuth2.0学习(1-5)授权方式2-简化模式(implicit grant type)
  8. 【JavaScript】Uncaught TypeError: Illegal invocation
  9. 从零开始学ios开发(十四):Navigation Controllers and Table Views(上)
  10. 向Windows 日志管理器写入系统程序日志信息
  11. 目标检测NMS非极大值抑制及改进
  12. js 去掉浏览器打印默认的页头页尾和打印背景图片
  13. mupdf添加图片水印_在博客园里给图片加水印(canvas + drag)
  14. Mac新手操作指南(三)
  15. 三、向SpringCloud注册Service服务(Restful服务)
  16. 使用计算机有关的活动,与计算机有关的传统文化活动策划书
  17. 内存对齐的规则以及作用 verygood!的一篇文章!
  18. [指北针分类信息软件 v1.5.2.1] 全自动分类信息软件+高效稳定建立SEO外部链接
  19. “工作三年,跳槽要求涨薪50%”,合理吗?
  20. petrel软件中的等值线导出然后加入Geomap4.0中成图/用python处理petrel导出的等值线以便于加入Geomap4.0中

热门文章

  1. Solace 调整最大连接数
  2. 第十一天-购物车订单系统的实现
  3. kotlin中的var和val与编译时常量
  4. 12.静态路由、静态缺省路由
  5. 基于Mui与H5+开发webapp的Android原生工程打包步骤(使用新版本5+SDK与Android studio)(部分内容转自dcloud官网)...
  6. 2005年全国信息学分区联赛模拟赛 猫猫的小鱼 题解
  7. 图像分割(四)—— Is Space-Time Attention All You Need for Video Understanding?
  8. 批量html转word 或者 pdf
  9. 如何把pdf文件放到服务器,将生成的PDF文件存储在服务器上
  10. 区块链与大数据结合分析