定义
命令模式将请求,封装成对象,以便使用不同的请求,队列或者日志来参数化其他的对象,命令模式也支持撤销的操作。
理解
在我看来命令模式最大的优势就是实现了调用者与被调用者之间的解耦,而被调用者往往不只一种,但被封装成对象之后,留出统一的接口,这样可以实现统一调用,而通过命令模式实现的撤销操作则用处更大了。
应用场景
-
- 利用命令模式可以将运算程序都打包成对象的形式,这样可以放在队列里,在调用就会极其方便
- 由于有强大的撤销功能,因此可用于原子性的事件之中
体现的设计原则
尽量降低对象之间的耦合关系
之所以命令模式在对对象调用起来极其方便,松耦合是主要原因,调用者甚至不知道调用的是谁,只要是实现了同一接口的对象都能传进调用者中。
优点
-
- 由于调用者与被调用者的松耦合关系,使程序在扩展起来变的容易
- 撤销模式在程序中还是比较实用的
缺点
-
- 对接受者和其他行为的包装势必会让程序产生更多的类
主要组成
调用者 | 调用命令的类 |
接收者 | 执行命令的类 |
抽象命令接口 | 为使命令调用时接口统一而做的抽象 |
具体命令接口 | 包装了接收者,以及一些行为 |
一般类图
下面是我程序类图
为了避免类图过于复杂,就没有去画下一个节目的调用关系
java源程序举例
举例是抽象一个遥控器(调用者)和节目(接收者),但是节目的封装命令分成两个类,一个是负责上一个节目,一个负责下一个节目。现在我们模仿遥控器操作一下换台
频道类
频道类里面简单演示了怎么去做撤销操作
package command_07;
public class Channel {
int state;//state是为了记录改变前的状态,以便撤销操作
public Channel() {
state=0;
}
public int getState() {
return state;
}
public void nextChannel() {
System.out.println("下一个节目");
state=0;
}
public void lastChannel() {
System.out.println("上一个节目");
state=1;
}
}
命令接口
package command_07;
public interface Command {
public void execute();//执行换台操作
public void undo();//执行撤回操作
}
上一个频道命令封装
package command_07;
public class ChannelLastCommand implements Command {
Channel channel;
int state;
public ChannelLastCommand(Channel channel) {
this.channel = channel;
}
public void execute() {
state=channel.getState();//在执行换台操作之前拿到之前的换台记录
channel.lastChannel();
}
public void undo() {//根据记录换回之前的频道
System.out.println("返回操作");
if(state==1){
channel.lastChannel();
}
if(state==0){
channel.nextChannel();
}
}
}
下一个频道命令封装
package command_07;
public class ChannelNextCommand implements Command {
Channel channel;
int state;
public ChannelNextCommand(Channel channel) {
this.channel = channel;
}
public void execute() {
state=channel.getState();
channel.nextChannel();
}
public void undo() {
System.out.println("返回操作");
if(state==1){
channel.lastChannel();
}
if(state==0){
channel.nextChannel();
}
}
}
遥控器
package command_07;
public class RemoteController {
Command command;
public void setCommand(Command command) {//作为调用者,传进谁的对象就执行谁的方法
this.command =command;
}
public void execcute(){
command.execute();
}
public void undo(){
command.undo();
}
}
客户端
package command_07;
public class Client {
public static void main(String[] args) {
Channel chan=new Channel();
ChannelLastCommand clc=new ChannelLastCommand(chan);//实例化封装的命令对象
ChannelNextCommand cnc=new ChannelNextCommand(chan);
RemoteController remotec=new RemoteController();
remotec.setCommand(clc);//把对象放进调用者中
remotec.execcute();
remotec.setCommand(cnc);
remotec.execcute();
remotec.undo();//撤销操作
}
}
本例就一个换频道的功能,如果要展现命令模式的威力,是应该多放点功能,例如电视的开关,音量的大小,不过本人比较懒就不做啦,而撤销功能的实现,则是每次换台就用0,1记录,要是想撤回,直接判断一下执行相应的换台操作就行,而要实现连续撤回,建议用栈,这样可以把操作都记录下来就行啦,最后愿你有所收获。