命令模式
定义
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations;
将一个请求封装为独享,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,提供命令的撤销和恢复功能。
分析
命令模式将一系列活动封装为一个命令,从而使得调用者与命令执行者之间没有依赖关系,而且利用封装+继承,可以十分方便地扩展命令种类,当然也可能造成类爆炸问题;
命令模式结合责任链模式可以实现命令族的解析任务;结合模板方法,在一定程度上可以减少命令类的数量;
实现
public abstract class Executor{ public astract void doSomething(); } public class ConcreteExecutor extends Executor{ public void doSomething(); } public abstract class Command{ public abstract void execute(); } public class ConcreteCommand extends Command{ private Executor executor; public ConcreteCommand(Executor e){ this.executor=e; } public void execute(){ this.executor.doSomething(); } } public class Invoker{ private Command command; public void setCommand(Command c){ this.command=c; } public void action(){ this.command.execute(); } } public class Client{ public static void main(String[] args){ Invoker invoker=new Invoker(); Executor executor=new ConcreteExecutor(); Command command=new ConcreteCommand(executor); invoker.setCommand(command); invoker.action(); } }
命令模式中,Client通过创建一个Concrete Command对象以及Executor对象,然后通过Invoker实现对命令的执行;
从类图以及代码中我们发现,Invoker类调用Command的execute方法,Command的execute方法是由Executor执行的,形成了Client->Invoker->Command->Executor这样的调用链条,似乎有一点长啊,我们试图分析它的合理性:
Client通知Invoker执行一个命令,与其说是要执行一个命令,不如说是要获得一个结果,这个结果的获得可能需要多个Command组成,每个Command有自己所对应的Executor来处理,合情合理;我们知道Command与Executor的调用关系是在Command的execute方法中建立的,我们可不可以在Command的execute方法里直接实现Executor做的事呢?很明显这样不好,一来职责不明(命令就是命令,只负责描述好命令本身即可,不应涉及实现),二来不宜扩展;那么Invoker这个类负责Command类的execute方法调用,Client直接调用Command的execute方法不行吗?从示例代码中来看,这样的确可以,但是实际上呢?Client作为客户,它和命令的执行者之间需要一个中介来完成沟通,就好像老师都是和学委交流,不是老师不能直接收作业而是这样老师就太忙了。。。。
与面向对象程序设计原则的关系
单一职责原则、依赖倒置原则、里氏替换原则、开闭原则、迪米特原则均有体现