在软件开发中,我们经常需要向某些对象发送请求(调用其中的某个或某些方法),但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,此时,我们特别希望能够以一种松耦合的方式来设计软件,使得请求发送者与请求接收者能够消除彼此之间的耦合,让对象之间的调用关系更加灵活,可以灵活地指定请求接收者以及被请求的操作。命令模式为此类问题提供了一个较为完美的解决方案。
命令模式
1 概述
将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。命令模式通过这种封装的方式实现将客户端和接收端解耦。
命令模式的几个角色:
- 抽象命令接口Command:
- 具体的命令对象ConcreteCommand:
- 接受者对象Receiver:
- 传递命令对象Invoker:
- 客户端对象Client:
命令关系类图:
2 示例
本例子是呼叫小爱同学帮你开灯的例子,你对小爱同学说:小爱同学帮我打开灯,然后小爱同学让灯自己打开了。
抽象命令接口Command:
1 2 3 4 5 6 7 8 9
|
public interface Command {
void execute(); }
|
具体的命令对象ConcreteCommand:(开灯命令,关灯命令)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
public class LightOnCommand implements Command{
private Light light;
public LightOnCommand(Light light) { this.light = light; }
@Override
public void execute() { light.lightOn(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
public class LightOffCommand implements Command{
private Light light;
public LightOffCommand(Light light) { this.light = light; }
@Override
public void execute() { light.lightOff(); } }
|
传递命令对象Invoker:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
public class XiaoAi {
private Command command;
public void setCommand(Command command) { this.command = command; }
public void doCommand() { command.execute(); } }
|
接受者对象Receiver:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public class Light {
public void lightOn() { System.out.println("灯打开了!!"); }
public void lightOff() { System.out.println("灯关上了!!"); } }
|
客户端对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
public class Client {
public static void main(String[] args) { XiaoAi xiaoAi = new XiaoAi(); Light light = new Light(); System.out.println("小爱同学帮我把灯开一下!"); LightOnCommand lightOnCommand = new LightOnCommand(light); xiaoAi.setCommand(lightOnCommand); xiaoAi.doCommand();
System.out.println("-------------------------------------------------"); System.out.println("小爱同学帮我关一下灯!"); LightOffCommand lightOffCommand = new LightOffCommand(light); xiaoAi.setCommand(lightOffCommand); xiaoAi.doCommand();
} }
|
测试结果:
1 2 3 4 5
| 小爱同学帮我把灯开一下! 灯打开了!! ------------------------------------------------- 小爱同学帮我关一下灯! 灯关上了!!
|
3 命令模式的优缺点
优点:
- 实现客户端和接受者之间的解耦。
- 可以动态的添加新的命令。
- 只需要调用同一个方法(doCommand方法)便可以实现不同的功能。
缺点:
- 实现一个具体的命令系统,可能要创建很多的具体命令对象。