定义:将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式又称为动作(Action)模式或事务(Transaction)模式。
包括三个核心对象:
1、调用者(Invoker):持有一个命令对象,并在某个时间点调用命令对象的execute()方法。
2、命令对象(Command):持有一个接收者,和一个execute()方法,在execute中执行接收者的动作。
3、接收者(Receiver):动作的执行者。
命令模式优点:
-
降低系统的耦合度:Command模式将调用操作的对象与知道如何实现该操作的对象解耦。
-
Command是头等的对象。它们可像其他的对象一样被操纵和扩展。
-
组合命令:你可将多个命令装配成一个组合命令,即可以比较容易地设计一个命令队列和宏命令。一般说来,组合命令是Composite模式的一个实例。
-
增加新的Command很容易,因为这无需改变已有的类。
5)可以方便地实现对请求的Undo和Redo。遥控器为例,java实现命令模式。实现灯和电视的开关。
直接上代码
Receiver:public class LightReceiver { public void on(){ System.out.println("电灯打开了..."); } public void off(){ System.out.println("电灯关闭了..."); } }
Command:
实现接口:
public interface Command {
public void execute();
public void undo();
}
电灯的开和关:
public class LightOffCommand implements Command{
LightReceiver light;
public LightOffCommand(LightReceiver light) {
this.light = light;
}
public void execute(){
light.off();
}
public void undo(){
light.on();
}
}
public class LightOnCommand implements Command{
LightReceiver light;
public LightOnCommand(LightReceiver light) {
this.light = light;
}
public void execute(){
light.on();
}
public void undo(){
light.off();
}
}
public class NoCommand implements Command{
/*
* 没有任何命令,空执行:用于初始化每个按钮,当调用空命令时
* 对象什么都不做即可
* 这也是一种设计模式,可以省掉对空的判断
* */
public void execute(){}
public void undo(){}
}
**Invoker:**调用者不需要知道实现什么命令,调用即可。
public class RemoteController {
//按钮命令数组
Command[] onCommands;
Command[] offCommands;
//撤销命令
Command undoCommand;
public RemoteController(){
onCommands = new Command[5];
offCommands = new Command[5];
for (int i=0;i<5;i++){
onCommands[i] = new NoCommand();
offCommands[i] = new NoCommand();
}
}
//给我们的按钮设置你需要的命令
public void setCommand(int no,Command onCommand, Command offCommand){
onCommands[no] = onCommand;
offCommands[no] = offCommand;
}
//按下开按钮
public void onButtonWasPushed(int no){
//找到你按下的开的按钮,并调用对应的方法
onCommands[no].execute();
//记录这次的操作,用于撤销
undoCommand = onCommands[no];
}
public void offButtonWasPushed(int no){
//找到你按下的关的按钮,并调用对应的方法
offCommands[no].execute();
//记录这次的操作,用于撤销
undoCommand = offCommands[no];
}
//按下撤销按钮
public void undoButtonWasPushed(){
undoCommand.undo();
}
}
Client:
public class Client {
public static void main(String[] args) {
//使用命令设计模式,完成通过遥控器,对电灯的操作
//创建电灯对象
LightReceiver lightReceiver = new LightReceiver();
//创建电灯相关的开关命令
LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);
TVReceiver tvReceiver = new TVReceiver();
TVOnCommand tvOnCommand = new TVOnCommand(tvReceiver);
TVOffCommand tvOffCommand = new TVOffCommand(tvReceiver);
//需要一个遥控器
RemoteController remoteController = new RemoteController();
//给我们的遥控器设置命令,比如no=0是电灯的开和关的操作
remoteController.setCommand(0,lightOnCommand,lightOffCommand);
System.out.println("------按下灯的开按钮-------");
remoteController.onButtonWasPushed(0);
System.out.println("------按下灯的关按钮-------");
remoteController.offButtonWasPushed(0);
System.out.println("------撤销------");
remoteController.undoButtonWasPushed();
remoteController.setCommand(1,tvOnCommand,tvOffCommand);
System.out.println("-----按下电视开-----");
remoteController.onButtonWasPushed(1);
}
}
我多写了一个电视,效果如下
执行的时序首先是调用者类,然后是命令类,最后是接收者类。也就是说一条命令的执行被分成了三步,它的耦合度要比把所有的操作都封装到一个类中要低的多,而这也正是命令模式的精髓所在:把命令的调用者与执行者分开,使双方不必关心对方是如何操作的。