设计模式-命令模式
命令模式(Command Pattern)
命令模式(Command Pattern):将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。
命令模式结构:

Command:
定义命令的接口,声明执行的方法。
ConcreteCommand:
具体的命令, 实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
Receiver:
接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
Invoker:
要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
Client:
创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。
//Receiver:接收者,真正执行命令的对象。
public class Light{
public void on(){System.out.println("开灯");}
public void off(){System.out.println(" 关灯");}
}
//Receiver:接收者,真正执行命令的对象。
public class TV{
public void on(){System.out.println("开电视");}
public void off(){System.out.println(" 关电视");}
}
//Command:定义命令的接口,声明执行的方法。
public interface Command{
public void execute();
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class NoCommand implements Command{
@Override
public void execute() {System.out.println("还没有为开关绑定操作");}
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class LightOnCommand implements Command{
private Light light;
public LightOnCommand(Light light) {this.light = light;}
@Override
public void execute() { light.on();}
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class LightOffCommand implements Command{
private Light light;
public LightOffCommand(Light light) {this.light = light;}
@Override
public void execute() { light.off();}
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class TVOnCommand implements Command{
private TV tv;
public TVOnCommand(TV tv) { this.tv = tv;}
@Override
public void execute() {tv.on();}
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class TVOffCommand implements Command{
private TV tv;
public TVOffCommand(TV tv) {this.tv = tv;}
@Override
public void execute() {tv.off();}
}
//Invoker:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
public class Invoker{
private Command[] onCommands;
private Command[] offCommands;
public Invoker() {
onCommands = new Command[7];
offCommands = new Command[7];
//初始化
Command noCommand = new NoCommand();
for (int i=0; i<7;i++){
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
}
public void setCommand(int slot,Command onCommand,Command offCommand){
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonPush(int slot){
onCommands[slot].execute();
}
public void offButtonPush(int slot){
offCommands[slot].execute();
}
}
//Client:创建具体的命令对象,并且设置命令对象的接收者。
// 注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。
public class Client{
public static void main(String[] args){
Invoker invoker = new Invoker();
Light light = new Light();
LightOnCommand lightOnCommand = new LightOnCommand(light);
LightOffCommand lightOffCommand = new LightOffCommand(light);
TV tv = new TV();
TVOnCommand tvOnCommand = new TVOnCommand(tv);
TVOffCommand tvOffCommand = new TVOffCommand(tv);
invoker.setCommand(0,lightOnCommand,lightOffCommand);
invoker.setCommand(1,tvOnCommand,tvOffCommand);
invoker.onButtonPush(0);
invoker.offButtonPush(0);
}
}
优点:
1、降低了系统耦合度。
2、新的命令可以很容易添加到系统中去。
缺点:
1、使用命令模式可能会导致某些系统有过多的具体命令类。
应用场景:
1、命令和实际的执行者分离,实际的操作都是通过invoker以及receiver去执行的
2、屏蔽了底层的复杂实现,对外提供了统一的表现
3、可以记录操作的历史记录
4、拓展性好,一方面,可以很方便地添加新的命令,如在word中添加插入html功能;另一方面,也可以把命令迁移到另一种场景下,如把word中的命令迁移到excel中
5、用户使用上,用户通过组合一些命令,可以实现宏的功能,效率更高

浙公网安备 33010602011771号