将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作
命令模式的几个角色:
1. 抽象命令接口Command:定义命令的接口,声明执行的方法。
2. 具体的命令对象ConcreteCommand:持有具体的接受者对象,完成具体的具体的命令。
3. 接受者对象Receiver:接受者对象,真正执行命令的对象。
4. 传递命令对象Invoker:持有命令对象,要求命令对象执行请求。
5. 客户端对象Client:创建具体命令的对象并且设置命令对象的接受者
优点: 1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。
缺点:使用命令模式可能会导致某些系统有过多的具体命令类。
实例
人给小爱机器人,发送控制命令,完成灯的开关操作
- 命令接口。一个命令对象通过在特定接收者上绑定一组动作来封装一个请求。命令对象将动作和接收者包装进了对象中,这个对象只暴露一个execute()方法,当方法被调用时,接收者会执行命令封装的动作。在使用者看来,并不需要接收者进行了哪些动作,只知道调用一下execute()方法,目的就可以达到
public interface Command {
void execute();
}
- 定义命令的接收者,这里的实例灯是命令的接收者,接收命令完成开关操作
public class Light {
public void on() {
System.out.println("开灯....");
}
public void off() {
System.out.println("关灯....");
}
}
- 具体的命令,实现Command接口,作为参数传递给命令的发出者,这里的接收者Light只可以接收两种命令,开和关
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
- 调用者,负责命令的下发或传递,持有命令接口,并封装set命令的方法
public class XiaoAi {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void doCommand() {
command.execute();
}
}
- 测试客户端类
public class TestClient {
public static void main(String[] args) {
Light light = new Light();
XiaoAi xiaoAi = new XiaoAi();
Command command = new LightOffCommand(light);
xiaoAi.setCommand(command);
xiaoAi.doCommand();
}
}
典型的使用,在redis和rabbitmq等客户端的实现时,因此后台使用的是命令的方式交互,所以jedis的客户端可以使用命令模式进行相关的实现…
另外,如果各命令之间有共同操作的话,可以定义一个抽象的父类去集成接口,所有的命令均由该父类继承实现即可.
总结
- 命令模式将发出请求对象、与执行请求对象通过命令进行解耦
- 调用者通过命令对象的execute便可以通知接收者
- 调用者的命令对象可以动态变更
- 接收者也可以同时接收多个命令然后一起调用
- 调用者可以直接实现请求而不转发给接收者