命令模式:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。
Command:
定义命令的接口,声明执行的方法。
ConcreteCommand:
命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
Receiver:
接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
Invoker:
要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
Client:
创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。
命令模式的优点:
1.命令模式将发出请求的对象和执行请求的对象解耦
2.在被解耦的两者之间间是通过命令对象进行沟通的,命令对象封装了一个或一组动作
3.调用者通过调用命令对象的execute方法发出请求,这使得接收者对象的劢作被调用
4.宏命令是命令的一种简单延伸,允许调用多个命令
package com.qinsoft.design; import java.util.ArrayList; import java.util.List; //Receiver:命令接收者 class Tv { public int currentChannel = 0; public void turnOn() { System.out.println("The televisino is on."); } public void turnOff() { System.out.println("The television is off."); } public void changeChannel(int channel) { this.currentChannel = channel; System.out.println("Now TV channel is " + channel); } } //Command:执行命令的接口 interface CommandInter { void execute(); } //ConcreteCommand:开机命令 class CommandOn implements CommandInter { private Tv myTv; public CommandOn(Tv tv) { myTv = tv; } public void execute() { myTv.turnOn(); } } //ConcreteCommand:关机命令 class CommandOff implements CommandInter { private Tv myTv; public CommandOff(Tv tv) { myTv = tv; } public void execute() { myTv.turnOff(); } } //ConcreteCommand:频道切换命令 class CommandChange implements CommandInter { private Tv myTv; private int channel; public CommandChange(Tv tv, int channel) { myTv = tv; this.channel = channel; } public void execute() { myTv.changeChannel(channel); } } //Invoker:可以看作是遥控器吧 class Control { private CommandInter onCommand, offCommand, changeChannel; public Control(CommandInter on, CommandInter off, CommandInter channel) { onCommand = on; offCommand = off; changeChannel = channel; } public void turnOn() { onCommand.execute(); } public void turnOff() { offCommand.execute(); } public void changeChannel() { changeChannel.execute(); } } //Client:测试类 public class Command { public static void main(String[] args) { // 命令接收者 Tv myTv = new Tv(); // 开机命令 CommandInter on = new CommandOn(myTv); // 关机命令 CommandInter off = new CommandOff(myTv); // 频道切换命令 CommandInter channel = new CommandChange(myTv, 2); // 命令控制对象 Control control = new Control(on, off, channel); //开机 control.turnOn(); //切换频道 control.changeChannel(); //关机 control.turnOff(); } }
在Invoker类遥控器中都是对应命令的CommandInter对象,所以也可以修改为一个list对象
//Invoker:可以看作是遥控器吧 class Control { public List<CommandInter> commands = new ArrayList<CommandInter>(); public List<CommandInter> getCommands() { return commands; } } //Client:测试类 public class Command { public static void main(String[] args) { // 命令接收者 Tv myTv = new Tv(); // 开机命令 CommandInter on = new CommandOn(myTv); // 关机命令 CommandInter off = new CommandOff(myTv); // 频道切换命令 CommandInter channel = new CommandChange(myTv, 2); Control control = new Control(); control.getCommands().add(on); control.getCommands().add(channel); control.getCommands().add(off); for(java.util.Iterator<CommandInter> it = control.getCommands().iterator();it.hasNext();){ //客户端直接调用execute方法,无需知道被调用者的其它更多类的方法名。 it.next().execute(); } } }
这样的话,使程序变得更加灵活一些。