内容简介:本文主要对命令模式进行概述讲解,并使用使用遥控器与灯来讲述命令模式中调用者与接收者的关系。命令模式(英语:
本文主要对命令模式进行概述讲解,并使用使用遥控器与灯来讲述命令模式中调用者与接收者的关系。
一、概述
命令模式(英语: Command pattern )是一种设计模式,它尝试以对象来代表实际行动。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被重复使用、撤销、撤销后重做。
这个是概念是来自维基百科,我觉得最容易理解,就是把命令封装成对象,使命令可以重复调用、撤销,降低了调用者和接受者的耦合,同时容易扩展出新的命令。
其他描述:
1.将“请求”封装成对象,以便使不同的请求、队列或日志来参数化其他对象,命令模式也支持可撤销操作。(Head First 设计模式)
2.命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。(Java与模式)
大家做适当参考,不理解可以先看看下面的源码!
二、结构
如图,这是命令模式的结构:
以用遥控器开灯为例(Head First 设计模式例子)
- Invoker:命令调用者,负责调用命令对象的请求—— 遥控器
- Command:声明了一个具体命令类实现的接口—— 命令的接口
-
ConcreteCommand:具体命令,实现了Invoker和Receiver之间的解耦,通常持有接收者对象的饮用—— 开灯按钮执行的命令
-
Receiver:命令接收者,真正接收命令并执行动作的对象—— 灯
- Client:客户端,创造具体的命令,并确定接收者
三、源代码
Receiver——二档亮度的灯
// 二档调节的灯,在这里作为接收者 public class Light { public static final String HIGH = "贼亮"; public static final String MEDIUM = "有点亮"; public static final String LOW = "快灭火了"; public static final String OFF = "真的灭火了~"; private String luminance; public Light() { this.luminance = OFF; } public void off() { System.out.println("灯关闭了"); this.luminance = OFF; } public void high() { System.out.println("贼亮"); this.luminance = HIGH; } public void medium() { System.out.println("挺亮地!"); this.luminance = MEDIUM; } public void low() { System.out.println("快灭火了"); this.luminance = LOW; } public String getLuminance(){ return this.luminance; } }
Command——做个命令接口,带撤销功能
public interface Command { void excute(); void undo(); }
LightHighCommand——高光命令
public class LightHighCommand implements Command { private Light light; private String preLuminance; @Override public void excute() { // 备份上一个命令,撤销使用 preLuminance = light.getLuminance(); light.high(); } @Override public void undo() { if (Light.HIGH.equals(preLuminance)){ light.high(); }else if(Light.MEDIUM.equals(preLuminance) ){ light.medium(); }else if (Light.LOW.equals(preLuminance)){ light.low(); }else if (Light.OFF.equals(preLuminance)){ light.off(); } } public LightHighCommand(Light light) { this.light = light; } // 智能遥控器按键功能可以控制多个灯 // 如果控制令一个接收者,可以传入,不用新建命令 public void setLight(Light light) { this.light = light; } }
LightOffCommand——关灯命令
public class LightOffCommand implements Command { private Light light; private String preLuminance; public LightOffCommand(Light light) { this.light = light; } @Override public void excute() { preLuminance = light.getLuminance(); light.off(); } @Override public void undo() { if (Light.HIGH.equals(preLuminance)){ light.high(); }else if(Light.MEDIUM.equals(preLuminance) ){ light.medium(); }else if (Light.LOW.equals(preLuminance)){ light.low(); }else if (Light.OFF.equals(preLuminance)){ light.off(); } } public void setLight(Light light) { this.light = light; } }
Invoker——遥控器
public class RemoteControl { private Command off; private Command high; private Command medium; private Command low; private Command preCommand; public void setOff(Command off) { this.off = off; } public void setHigh(Command high) { this.high = high; } public void setMedium(Command medium) { this.medium = medium; } public void setLow(Command low) { this.low = low; } public void lightOff() { off.excute(); preCommand = off; } public void lightHigh() { high.excute(); preCommand = high; } public void lightMedium() { medium.excute(); preCommand = medium; } public void lightLow() { low.excute(); preCommand = low; } public void undo() { if (preCommand == null) { System.out.println("无法撤销"); } else { preCommand.undo(); } } }
Client——客户端
public class Client { public static void main(String[] args) { // 创建接收者 Light light = new Light(); // 创建命令 Command lightHighCommand = new LightHighCommand(light); Command lightOffCommand = new LightOffCommand(light); // 创建调用者 RemoteControl remoteControl = new RemoteControl(); remoteControl.setHigh(lightHighCommand); remoteControl.setOff(lightOffCommand); // 调用 remoteControl.lightHigh(); remoteControl.lightOff(); remoteControl.undo(); } } ————————>结果 贼亮 灯关闭了 贼亮
以上就是一个带撤回功能的命令模式,其中:
如果想实现 多步撤回 ,可以考虑把调用者中的preCommand换成stack;
如果想实现 组合命令 ,可以重新创建一个 宏命令 ,如下
public class MacroCommand implements Command { private Command[] commands; public MacroCommand(Command[] commands) { this.commands = commands; } @Override public void excute() { for (Command command : commands) { command.excute(); } } @Override public void undo() { for (Command command : commands) { command.undo(); } } }
你可以用这个命令实现任何形式的命令组合,甚至如果你觉得你的遥控器可以控制空调,控制电源,控制电饭锅,你甚至可以把这些命令组合进来~
四、命令模式的优缺点
优点
-
解耦合:将命令调用者和命令执行者通过命令进行解耦,命令调用者不关心由谁来执行命令,只要命令执行就可以
-
更动态的控制:请求被封装成对象后,可以轻易的参数化、队列化、日志化,使系统更加灵活。
- 更容易的命令组合 :有了宏命令后,可以任意的对命令进行组合
- 更好扩展性 :可以轻易的添加新的命令,并不会影响到其他的命令
缺点
- 命令过多时,会创建了过多的命令类,不方便进行管理
五、总结
本文对命令模式作了简单的介绍,命令模式只要明白调用者如何通过命令与接收者交互,就比较好理解。在实际应用中,命令模式可以用在并行处理、事务行为、线程池等地方。例如传统的线程池就有addTask()方法将命令加入到等待被执行的队列中,允许多线程执行实现 java.lang.Runnable
的命令,尽管线程池本身对具体的任务毫无认知。
本文首发于cdream个人博客
欢迎转载,转载请注明出处!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 设计模式——订阅模式(观察者模式)
- 设计模式-简单工厂、工厂方法模式、抽象工厂模式
- java23种设计模式-门面模式(外观模式)
- 设计模式-享元设计模式
- Java 设计模式之工厂方法模式与抽象工厂模式
- JAVA设计模式之模板方法模式和建造者模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Mission Python
Sean McManus / No Starch Press / 2018-9-18 / GBP 24.99
Launch into coding with Mission Python, a space-themed guide to building a complete computer game in Python. You'll learn programming fundamentals like loops, strings, and lists as you build Escape!, ......一起来看看 《Mission Python》 这本书的介绍吧!