定义
将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。
角色
Command:定义命令的统一接口
ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
Receiver:命令的实际执行者
Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。
命令模式的本质就在于将命令进行封装,将发出命令的责任和执行命令的责任分开,使发送者只需要知道如何发送命令即可,不需要了解命令是如何实现的,甚至命令执行是否成功都不需要理会。同时命令模式使得请求也变成了一个对象,它像其他对象一样可以被存储和传递。
优缺点
优点:
降低了系统耦合度
新的命令可以很容易添加到系统中去。
缺点:
- 使用命令模式可能会导致某些系统有过多的具体命令类。
实例
以遥控器操控电视机为例。
电视机:
/**
* 电视机
*/
public class Television {
public void open() {
System.out.println("打开电视机......");
}
public void close() {
System.out.println("关闭电视机......");
}
public void changeChannel() {
System.out.println("切换电视频道......");
}
}
命令接口
/**
* 命令接口,为所有的命令声明一个接口。所有的命令都应该实现它
*/
public interface Command {
void execute();
}
遥控器:
/**
* 遥控器
*/
public class Controller {
private Command openTVCommand;
private Command closeTVCommand;
private Command changeChannelCommand;
public Controller(Command openTvCommand,Command closeTvCommand,Command changeChannelCommand){
this.openTVCommand = openTvCommand;
this.closeTVCommand = closeTvCommand;
this.changeChannelCommand = changeChannelCommand;
}
/**
* 打开电视剧
*/
public void open(){
openTVCommand.execute();
}
/**
* 关闭电视机
*/
public void close(){
closeTVCommand.execute();
}
/**
* 换频道
*/
public void change(){
changeChannelCommand.execute();
}
}
具体按钮对象:
/**
* 遥控器开机按钮
*/
public class OpenTvCommand implements Command {
private Television tv;
public OpenTvCommand() {
tv = new Television();
}
@Override
public void execute() {
tv.open();
}
}
/**
* 遥控器调频按钮
*/
public class ChangeChannelCommand implements Command {
private Television tv;
public ChangeChannelCommand() {
tv = new Television();
}
@Override
public void execute() {
tv.changeChannel();
}
}
/**
* 遥控器关机按钮
*/
public class CloseTvCommand implements Command {
private Television tv;
public CloseTvCommand() {
tv = new Television();
}
@Override
public void execute() {
tv.close();
}
}
测试:
public static void main(String[] args) {
Command openCommand, closeCommand, changeCommand;
openCommand = new OpenTvCommand();
closeCommand = new CloseTvCommand();
changeCommand = new ChangeChannelCommand();
Controller control = new Controller(openCommand, closeCommand, changeCommand);
// 打开电视机
control.open();
// 换频道
control.change();
// 关闭电视机
control.close();
}
控制台输出:
打开电视机......
切换电视频道......
关闭电视机......