命令模式是一种高内聚的模式,定义为:将一个请求封装为一个对象,从而使不同的请求把客户端参数化,将请求排队或记录请求日志,可以提供命令的撤销和恢复功能。
命令模式通常有三个角色:
- Receiver接收者角色。接收到命令后执行具体任务
- Command命令角色。需要执行的所有命令都在这里定义
- Invoker调用者角色。接收到命令,并执行命令
下面看一段通用代码:
//接收者,可以是多个,所以定义为抽象类 public abstract class Receiver{ //抽象接收者,定义每个接收者必须完成的任务 public abstract void doSomething(); } //具体的接收者 public class ConcreateReceiver1 extends Receiver{ //处理逻辑 public void doSomething(){} } public class ConcreateReceiver2 extends Receiver{ //处理逻辑 public void doSomething(){} } //抽象的Command类 public abstract class Command{ //每个命令类都必须有一个执行命令的方法 public abstract void excute(); } //具体的Command类,通过构造函数确定是针对哪个接收者发出的命令 public class ConcreateCommand1 extends Command{ //对哪个receiver类进行命令处理 private Receiver receiver; //构造函数接收者 public ConcreateCommand1(Receiver receiver){ this.receiver = receiver; } //必须实现一个命令 public void excute(){ this.receiver.doSomething(); } } public class ConcreateCommand2 extends Command{ //对哪个receiver进行命令处理 private Receiver receiver; public ConcreateCommand2(Receiver receiver){ this.receiver = receiver; } //必须实现一个命令 public void excute(){ this.receiver.doSomething(); } } //调用者类,仅实现命令的传递 public class Invoker{ private Command command; //受气包,接收命令 pubulic void setCommand(Command command){ this.command = command; } //执行命令 public void action(){ this.command.excute(); } } //场景类 public class Client{ public static void main(String[] args){ //首先声明调用者 Invoker invoker = new Invoker(); //定义接收者 Receiver receiver = new ConcreateReceiver1(); //定义命令,指定接收者 Command command = new ConcreateCommand(receiver); //把命令交给调用者执行 invoker.setCommand(command); invoker.action(); } }
命令模式的优点:
- 类间解耦。调用者和接收者没有任何依赖关系,调用者只需要调用Command抽象类的excute方法就可以,不需要了解是哪个接收者执行
- 可扩展性。Command的子类非常容易扩展,而调用者不会和更高层模块耦合
- 可以结合其他模式取得更好的表现。和责任链模式组合实现命令族解析任务;和模板方法模式组合减少Command子类膨胀问题
命令模式缺点:
使用不当,会产生command子类膨胀的问题。
应用场景:
所有你认为是命令的地方都可以使用。比如GUI的点击任务,DOS窗口的模拟命令等。
最佳实践:
在通用示例中,Receiver角色暴露给了Client类!这是不应该存在的依赖,实际应用中,receiver模块一般会被封装掉(除非必要,比如有撤销处理),下面展示优化的例子:
public abstract class Command { //定义一个子类的全局共享变量 protected final Receiver receiver; //实现类必须定义一个接收者 public Command(Receiver _receiver){ this.receiver = _receiver; } //每个命令类都必须有一个执行命令的方法 public abstract void execute(); } public class ConcreteCommand1 extends Command { //声明自己的默认接收者 public ConcreteCommand1(){ super(new ConcreteReciver1()); } //设置新的接收者 public ConcreteCommand1(Receiver _receiver){ super(_receiver); } //每个具体的命令都必须实现一个命令 public void execute() { //业务处理 super.receiver.doSomething(); } } public class ConcreteCommand2 extends Command { //声明自己的默认接收者 public ConcreteCommand2(){ super(new ConcreteReciver2()); } //设置新的接收者 public ConcreteCommand2(Receiver _receiver){ super(_receiver); } //每个具体的命令都必须实现一个命令 public void execute() { //业务处理 super.receiver.doSomething(); } } public class Client { public static void main(String[] args) { //首先声明调用者Invoker Invoker invoker = new Invoker(); //定义一个发送给接收者的命令 Command command = new ConcreteCommand1(); //把命令交给调用者去执行 invoker.setCommand(command); invoker.action(); } }