文档章节

《设计模式》之命令模式

h
 haidao1992
发布于 2017/06/24 19:59
字数 1603
阅读 20
收藏 0

#程序员薪资揭榜#你做程序员几年了?月薪多少?发量还在么?>>>

一、命令模式定义

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

如老板命令你完成一个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.   
  5.     public Light(String location) {  
  6.         this.location = location;  
  7.     }  
  8.   
  9.     public void on() {  
  10.         level = 100;  
  11.         System.out.println("Light is on");  
  12.     }  
  13.   
  14.     public void off() {  
  15.         level = 0;  
  16.         System.out.println("Light is off");  
  17.     }  
  18.     //调整灯光的亮度  
  19.     public void dim(int level) {  
  20.         this.level = level;  
  21.         if (level == 0) {  
  22.             off();  
  23.         }  
  24.         else {  
  25.             System.out.println("Light is dimmed to " + level + "%");  
  26.         }  
  27.     }  
  28.    //获取灯光的亮度  
  29.     public int getLevel() {  
  30.         return level;  
  31.     }  
  32. }  

(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.    
  9.     public CeilingFan(String location) {  
  10.         this.location = location;  
  11.         speed = OFF;  
  12.     }  
  13.     
  14.     public void high() {  
  15.         speed = HIGH;  
  16.         System.out.println(location + " ceiling fan is on high");  
  17.     }   
  18.    
  19.     public void medium() {  
  20.         speed = MEDIUM;  
  21.         System.out.println(location + " ceiling fan is on medium");  
  22.     }  
  23.    
  24.     public void low() {  
  25.         speed = LOW;  
  26.         System.out.println(location + " ceiling fan is on low");  
  27.     }  
  28.     
  29.     public void off() {  
  30.         speed = OFF;  
  31.         System.out.println(location + " ceiling fan is off");  
  32.     }  
  33.     
  34.     public int getSpeed() {  
  35.         return speed;  
  36.     }  
  37. }  

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.    
  8.     public void execute() {  
  9.         level = light.getLevel();  
  10.         light.on();  
  11.     }  
  12.    
  13.     public void undo() {//将灯光的亮度调到前一次的水平实现撤销  
  14.         light.dim(level);  
  15.     }  
  16. }  


(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.    
  8.     public void execute() {  
  9.         level = light.getLevel();  
  10.         light.off();  
  11.     }  
  12.    
  13.     public void undo() {  
  14.         light.dim(level);  
  15.     }  
  16. }  


(4)DimmerLightOnCommand:开启暗光

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


(5)DimmerLightOffCommand:关闭暗光

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

(6)CeilingFanHighCommand:风扇高转速

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

(7)CeilingFanMediumCommand:风扇中转速

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

(8)CeilingFanLowCommand:风扇低转速

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

(9)CeilingFanOffCommand:关闭风扇

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

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

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

5.测试

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


运行结果:

  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  

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

© 著作权归作者所有

h
粉丝 1
博文 37
码字总数 32506
作品 0
浦东
程序员
私信 提问
加载中

评论(0)

《PHP设计模式大全》系列分享专栏

《PHP设计模式大全》已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/read/201739.html 文章 php设计模式介绍之编程惯用法第1/3页 php设计模式介绍之值对象模式第1/5页...

kaixin_code
2018/11/06
235
0
【java设计模式】-00目录

开篇 【java设计模式】-01设计模式简介 创建型模式: 【java设计模式】-02工厂模式(Factory Pattern) 结构型模式: 【java设计模式】-07适配器模式(Adapter Pattern) 行为型模式: 【jav...

osc_3www0d3o
2018/06/18
28
0
极速理解设计模式系列【目录索引】

这是一个老生常谈的设计模式系列文章,本系列力图从最简洁的语言和最易理解的实例来让大家认识设计模式的思想和思路,从而在实际项目中能够用到一二。现在将本系列文章详列如下: 极速理解设...

程兴亮
2011/10/31
0
0
php 23种设计模式 - 设计模式简介以及分类

一、 Introduction【介绍】 设计模式:提供了一种广泛的可重用的方式来解决我们日常编程中常常遇见的问题。设计模式并不一定就是一个类库或者第三方框架,它们更多的表现为一种思想并且广泛地...

osc_pa25fsb2
2019/07/03
13
0
spring 中常用的设计模式

一、 Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模式: DispatcherServlet 策略模式: HandlerMa...

osc_bq1qsg6s
2019/05/21
20
0

没有更多内容

加载失败,请刷新页面

加载更多

总结:Spring boot熔断

一、介绍 1、熔断的目的:是为了保证服务高可用,不能因为系统中的一个小服务不可用,从而导致整个系统崩溃。 2、熔断的原理:对于使用相关注解的类或者方法,系统会监控其错误,如果多次出现...

浮躁的码农
22分钟前
16
0
抽象工厂

1. 介绍 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式,是工厂方法模式的升级版,在有多个业务品种、业务分类时,...

steven-黄笑笑
27分钟前
22
0
Autoruns显示windows系统所有启动项

如题,可以显示所有启动项,然后把不需要的启动项都取消勾选即可。而对于“服务”项,建议不要在里面去掉勾选,因为这样会禁止服务,容易出错。我通常都会打开电脑的”服务“,按启动类型排序...

ethanleellj
28分钟前
11
0
多线程基础学习

线程和进程有区别? 进程=加载上下文+执行程序+保存上下文 进程属于资源分配的最小单位,线程属于执行任务的最小单位。 线程6种状态: 1、New 尚未启动的线程的线程状态。 2、Runnable 可运行...

javazyw
56分钟前
30
0
英文对“ Big O”符号的解释是什么? - What is a plain English explanation of “Big O” notation?

问题: 我希望尽可能少用正式的定义和简单的数学方法。 解决方案: 参考一: https://stackoom.com/question/22l0/英文对-Big-O-符号的解释是什么 参考二: https://oldbug.net/q/22l0/What...

javail
58分钟前
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部