"围观"设计模式(23)--行为型之命令模式(Command Pattern)
来源:互联网 发布:软件人才培训班 编辑:程序博客网 时间:2024/05/02 00:52
在面向对象程式设计的范畴中,命令模式是一种设计模式,它尝试以物件来代表实际行动。命令物件可以把行动(action) 及其参数封装起来,于是这些行动可以被:
- 重复多次
- 取消(如果该物件有实作的话)
- 取消后又再重做
这些都是现代大型应用程序所必须的功能,即“复原”及“重复”。----WIKIPEDIA
个人理解
命令模式是一个高内聚的模式,它将一个请求封装为一个对象,让你使用不同的请求将客户端参数化,在项目中应用比较广泛,他的封装性比较好,将请求方和接收方分离开来,扩展性较好。命令模式中主要有三种角色,一个是命令的接受者(Receiver),他负责对于收到的命令作出响应。一个是命令(Command)角色,他负责定义接受者需要执行什么样的命令。另一个是调用者(Invoker),接收命令调用并执行命令。但是命令模式也存在不足,如果命令较多的时候那么会存在多个子类,导致臃肿,可以结合其他的模式进行设计,如结合责任链模式实现命令的解析、结合模板方法模式减少子类的膨胀问题。
案例解析
命令模式模板
三个主要角色
1. 接收者(Receiver)
负责具体执行哪些动作,也就是说他只负责提供一些任务的具体实现,不负责其他的部分。
2. 命令(Command)角色
负责定义好具体的命令,包括规定好接收者需要执行的哪些动作。
3. 调用者(Invoker)角色
负责调用命令执行,不需要知道谁是接收者,以及接收者怎么去执行,因为需要知道怎么执行的是接收者,他定义了任务的具体实现,另外不需要知道接收者是谁,这在命令角色中已经定义了哪些接收者执行哪些动作。
命令模式模板类结构图
主要代码
接收者角色:
public interface Receiver {public void doSomthing();}
具体实现类
public class Receiver1 implements Receiver {@Overridepublic void doSomthing() {System.out.println("Receiver1");}}
命令角色
public abstract class Command {protected Receiver receiver;public Command(Receiver receiver) {this.receiver = receiver;}public abstract void execute();}
具体实现类
public class Command1 extends Command {public Command1(Receiver receiver) {super(receiver);}@Overridepublic void execute() {this.receiver.doSomthing();}}
调用者角色
public class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void action() {this.command.execute();}}
测试类
public class Test {public static void main(String[] args) {// 调用者Invoker invoker = new Invoker();// 接收者Receiver receiver = new Receiver1();// 命令角色Command command = new Command1(receiver);invoker.setCommand(command);invoker.action();}}
拓展案例解读
案例背景介绍
以家庭雇佣管家和保姆等佣人为例子,主要的人物有,老板、佣人,其中老板在命令模式中相当于调用者,而佣人则相当于接收者,老板对于佣人的指令相当于命令角色。那么从这一点出发来想这个案例中老板发号施令的好处所在,老板只需要说一下命令,然后,具体谁去做,怎么做老板不需要知道的,只需要等待命令的结果就行了。
案例中类结构图
主要代码
接收者角色
public interface Person {/** * 劈柴 */public void chopping();/** * 做饭 */public void makeFood();/** * 喂马 */public void feedHorse();/** * 周游世界 */public void travelWorld();}
具体实现类
public class Man implements Person{@Overridepublic void chopping() {System.out.println("Man --- chopping");}@Overridepublic void makeFood() {System.out.println("Man --- makeFood");}@Overridepublic void feedHorse() {System.out.println("Man --- feedHorse");}@Overridepublic void travelWorld() {System.out.println("Man --- travelWorld");}}
public class Woman implements Person{@Overridepublic void chopping() {System.out.println("Woman --- chopping");}@Overridepublic void makeFood() {System.out.println("Woman --- makeFood");}@Overridepublic void feedHorse() {System.out.println("Woman --- feedHorse");}@Overridepublic void travelWorld() {System.out.println("Woman --- travelWorld");}}
命令角色
public abstract class Command {protected Man man = new Man();protected Woman woman = new Woman();public abstract void executeBossCommand();}具体实现类
public class ChoppingCommand extends Command {@Overridepublic void executeBossCommand() {this.man.chopping();}}
public class MakeFoodCommand extends Command {@Overridepublic void executeBossCommand() {this.woman.makeFood();}}
调用者
public class Boss {private Command command;public void setCommand(Command command) {this.command = command;}public void executeCommand(){this.command.executeBossCommand();}}
测试类
public class MainTest {public static void main(String[] args) {Boss boss = new Boss();Command command1 = new ChoppingCommand();boss.setCommand(command1);boss.executeCommand();Command command2 = new MakeFoodCommand();boss.setCommand(command2);boss.executeCommand();}}
模式扩展
情景介绍
假如此时老板很明确的是男的佣人要去劈柴和喂马,而女佣人可以去做饭和旅游,那么这种情况下是不是可以进行扩展呢?
主要代码
代码分析,如果说可以扩展的话,那么其余的部分需要进行变更,也就是在上面例子的基础上只需要扩展子类即可,那么这里我不再列出其类的结构图了,因为基本是一致的。
扩展命令角色为ManCommand和WomanCommand两个具体的实现类。
ManCommand
public class ManCommand extends Command{/** * 让男人干点劈柴喂马的事 */@Overridepublic void executeBossCommand() {this.man.chopping();this.man.feedHorse();}}
WomanCommand
public class WomanCommand extends Command{/** * 让女人干点做饭和周游世界的事 */@Overridepublic void executeBossCommand() {this.woman.makeFood();this.woman.travelWorld();}}
测试类
public class MainTest {public static void main(String[] args) {Boss boss = new Boss();ManCommand manCommand = new ManCommand();boss.setCommand(manCommand);boss.executeCommand();WomanCommand womanCommand = new WomanCommand();boss.setCommand(womanCommand);boss.executeCommand();}}从此案例可以看出命令模式的确扩展性很强,符合开闭原则。
命令模式的优点
1. 解耦:调用者和接受者之间没有关系,调用者在调用的时候,只需要执行命令(Command)中的执行方法就可以了,不需要了解哪个接收者去实际的执行。
2. 可扩展性:Command部分容易扩展,调用者不需要知道有什么改变,维持原有的设计即可完成扩展,从这点上看,符合开闭原则,对修改关闭对于扩展开放。
命令模式的缺点
命令过多的时候,会导致子类过多,系统类臃肿且难于维护,不过可以结合其他的设计模式进行整合,使得优点得到更好的发挥,如结合模板方法模式解决子类过多的问题。
命令模式的适用场景
只要可认为是命令的地方都可以采用命令模式,比如,按钮的点击和拖拽,相当于两个命令,而按钮作为接受者,此时就可以采用命令模式进行设计。
源码下载
设计模式源码下载地址
- "围观"设计模式(23)--行为型之命令模式(Command Pattern)
- 设计模式(行为型)之命令模式(Command Pattern)
- "围观"设计模式(18)--行为型之模板方法模式(TemplateMethod Pattern)
- "围观"设计模式(19)--行为型之观察者模式(Observer Pattern)
- "围观"设计模式(20)--行为型之策略模式(Strategy Pattern)
- "围观"设计模式(21)--行为型之状态模式(State Pattern)
- "围观"设计模式(22)--行为型之职责链模式(Chain Of Responsibility Pattern)
- "围观"设计模式(24)--行为型之访问者模式(Visitor Pattern)
- "围观"设计模式(25)--行为型之中介者模式(Mediator Pattern)
- "围观"设计模式(26)--行为型之备忘录模式(Memento Pattern)
- "围观"设计模式(27)--行为型之解释器模式(Interpreter Pattern)
- 23种设计模式(14)_行为型_命令模式(Command Pattern)
- 行为型模式:命令模式(Command Pattern)
- 设计模式之命令(Command)---对象行为型模式
- 【设计模式】行为型模式——命令模式(Command Pattern)
- 行为型模式5:命令模式(Command Pattern)
- 设计模式(8)——命令模式(Command Pattern,行为型)
- 【设计模式】行为模式之Command命令
- 几种常见的Shell
- 迭代器失效小分析
- spring和mybaits整合
- div可拉伸插件
- FFMpeg在Windows下搭建开发环境
- "围观"设计模式(23)--行为型之命令模式(Command Pattern)
- Shell脚本语言与编译型语言的差异
- 值得学习的Unity工程或插件项目
- 111. Minimum Depth of Binary Tree 二叉树的最小深度
- Summary Ranges
- iOS 截屏 长图 拼图
- 《剑指offer》:[49]把字符串转化成整数
- 什么时候使用Shell
- wx/msw/setup.h 错误