"围观"设计模式(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部分容易扩展,调用者不需要知道有什么改变,维持原有的设计即可完成扩展,从这点上看,符合开闭原则,对修改关闭对于扩展开放。


命令模式的缺点

命令过多的时候,会导致子类过多,系统类臃肿且难于维护,不过可以结合其他的设计模式进行整合,使得优点得到更好的发挥,如结合模板方法模式解决子类过多的问题。


命令模式的适用场景

只要可认为是命令的地方都可以采用命令模式,比如,按钮的点击和拖拽,相当于两个命令,而按钮作为接受者,此时就可以采用命令模式进行设计。


源码下载

设计模式源码下载地址


2 0