深入浅出设计模式-006:命令模式(Command Pattern)
一:命令模式可以将“动作的请求者”从“动作的执行者”对象中解耦。
创建命令对象
利用setCommand将命令对象存储在调用者中
利用execute要求调用者执行命令
二:命令模式:将“请求”封装成对象,以便使用不同的请求或者队列或者日志来参数化其他对象。
也支持可撤销操作。
public class Light{
public String location;
public Light(String location){
this.location = location;
}
public void On(){
Console.WriteLine(location + "/t Light On");
}
public void Off(){
Console.WriteLine(location + "/t Light Off");
}
}
public interface Command{
//执行命令
void execute();
}
public class LightOnCommand : Command{
Light light;
public LightOnCommand(Light light){
this.light = light;
}
public void execute(){
light.On();
}
}
public class LightOffCommand : Command{
Light light;
public LightOffCommand(Light light){
this.light = light;
}
public void execute(){
light.Off();
}
}
public class SimpleRemoteControl{
Command slot;
public SimpleRemoteControl() { }
//接受命令
public void setCommand(Command command){
slot = command;
}
public void buttonWasPressed(){
slot.execute();
}
}
class Program//此乃客户
{
static void Main(string[] args)
{
//调用者,用来发出请求
SimpleRemoteControl remote = new SimpleRemoteControl();
//创建对象,此对象即请求的接受者
Light light = new Light("1");
//创建命令,
LightOnCommand lightOn = new LightOnCommand(light);
//将命令传给调用者,即(服务员下单)
remote.setCommand(lightOn);
remote.buttonWasPressed();
}
}
三:命令模式将发出请求的对象和执行请求的对象解耦
在被解耦的两者之间是通过命令对象进行沟通的,命令对象封装了接受者的一个或一组动作
调用者通过调用命令对象的EXECUTE发出请求,这会使得接受者的动作被调用
调用者可以接受命令当做参数,甚至在运行时动态地进行
命令可以支持撤销,撤销是实现一个UNDO方法来回到EXECUTE被执行前的状态
宏命令是命令的一种简单延伸,允许调用多个命令。宏方法也可以支持撤销。
命令可以用来实现日志和事物系统
public interface Command{
//执行命令
void execute();
void undo();
}
public class NoCommand : Command{
public void execute()
{
return ;
}
public void undo()
{
return;
}
}
public class MacroCommand : Command{
Command[] commands;
public MacroCommand(Command[] commands){
this.commands = commands;
}
public void execute(){
for(int index=0; index<commands.Length; index++){
commands[index].execute();
}
}
public void undo(){
for (int index = 0; index < commands.Length; index++){
commands[index].undo();
}
}
}
public class LightOnCommand : Command{
Light light;
public LightOnCommand(Light light){
this.light = light;
}
public void execute(){
light.On();
}
public void undo(){
light.Off();
}
}
public class LightOffCommand : Command{
Light light;
public LightOffCommand(Light light){
this.light = light;
}
public void execute(){
light.Off();
}
public void undo(){
light.On();
}
}
public class RemoteControl{
Command[] onCommands;
Command[] offCommands;
Command undoCommand;
public RemoteControl(){
onCommands = new Command[7];
offCommands = new Command[7];
//可以避免在每次调onButtonWasPushed时检测命令是否为空
Command noCommand = new NoCommand();
for (int index = 0; index < 7; index++){
onCommands[index] = noCommand;
offCommands[index] = noCommand;
}
undoCommand = noCommand;
}
public void setCommand(int slot, Command onCommand, Command offCommand){
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPushed(int slot){
onCommands[slot].execute();
undoCommand = onCommands[slot];
}
public void offButtonWasPushed(int slot){
offCommands[slot].execute();
undoCommand = offCommands[slot];
}
public void undoButtonWasPushed(){
undoCommand.undo();
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.Append("/n------ Remote Control -------/n");
for (int i = 0; i < onCommands.Length; i++){
sb.Append("[slot " + i + "] " + onCommands[i].GetType().Name
+ " " + offCommands[i].GetType().Name + "/n");
}
return sb.ToString();
}
}
class Program
{
static void Main(string[] args)
{
//管理一组命令对象,每个按钮都有一个命令对象。
//每次按下按钮,就调用相应的**ButtonWasPushed方法,间接调用EXECUTE方法
RemoteControl remoteControl = new RemoteControl();
Light klight = new Light("1");
//利用Command接口,每个动作都被实现成一个简单得的命令对象。
//命令对象持有对一个厂商类的实例的引用,并实现EXECUTE方法
//这个方法会调用厂商类实例的一个或多个方法,完成特定的行为。
LightOnCommand lighton = new LightOnCommand(klight);
LightOffCommand lightoff = new LightOffCommand(klight);
//1号卡槽,控制电灯开关
remoteControl.setCommand(1, lighton, lightoff);
remoteControl.onButtonWasPushed(1);
remoteControl.offButtonWasPushed(1);
remoteControl.undoButtonWasPushed();
Command[] partyOn = { lighton};
Command[] partyOff = { lightoff };
MacroCommand partyOnCmd = new MacroCommand(partyOn);
MacroCommand partyOffCmd = new MacroCommand(partyOff);
//0号卡槽,控制所有设备的开关
remoteControl.setCommand(0, partyOnCmd, partyOffCmd);
remoteControl.onButtonWasPushed(0);
remoteControl.offButtonWasPushed(0);
}
}