命令模式:将“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也支持可撤销的操作。
一个命令对象通过在特定的接收者上面绑定一组动作来封装这个请求。要达到这一点,命令对象将接收者和动作封装在一个对象中,只暴露出一个Execute()方法。当此方法调用则进行接收者的动作。从外面看来,其他对象不需要知道哪个接收者进行了哪些动作,只知道如果调用了Execute()方法,请求的目的就能达到。
例如有一个简单的遥控器能够控制灯的开关:
首先定义Command接口:
1 interface ICommand 2 3 { 4 5 void Execute(); 6 7 }
随后创建接收者:
1 public class Light 2 3 { 4 5 public void LightOn() 6 7 { 8 9 Console.WriteLine("灯亮"); 10 11 } 12 13 public void LightOff() 14 15 { 16 17 Console.WriteLine("灯灭"); 18 19 } 20 21 }
创建命令对象:
1 public class LightOnCommand : ICommand 2 3 { 4 5 public Light light; 6 7 public LightCommand(Light light) 8 9 { 10 11 this.light = light; 12 13 } 14 15 public void Execute() 16 17 { 18 19 light.LightOn(); 20 21 } 22 23 }
实现遥控器:
1 public class RemoteCtrl 2 3 { 4 5 ICommand command = new LightCommand(new Light()); 6 7 public void Click() 8 9 { 10 11 command.Execute(); 12 13 } 14 15 }
若有多个命令对象可以创建命令对象数组,并创建一个NoComand对象作为初始化使用,这样避免无命令的时候的错误。
当有多个命令的时候,可能会遇见撤销的操作,这时候可以在命令对象中增加UnDo操作,表示撤回例如:
1 public class LightOnCommand : ICommand 2 3 { 4 public Light light; 5 6 public LightCommand(Light light) 7 8 { 9 10 this.light = light; 11 12 } 13 14 public void Execute() 15 16 { 17 18 light.LightOn(); 19 20 } 21 22 Public void UnDo(){ 23 24 Light.LightOff(); 25 26 } 27 28 }
可以在操作者对象设置一个Command命令,存储撤回的Command。即执行UnDo操作。
使用宏命令(Party模式),能够一次性执行多个命令。创建新的Command,将其他Command放入这里,在一个Execute中,执行所有的Command。
如果有多级需要撤销的可以考虑采用队列。
一些常见问题:
接收者是否一定要存在?
一般来说,我们尽量设计“傻瓜模式”,它只懂得调用一个接收者的行为。然而也可以设计成“聪明模式”,在Execute执行逻辑细节,但是这样调用者和接收者的解耦程度是比不上“傻瓜模式”的,而且也不能将接收者当作对象传递。
宏命令可以在Execute中执行所需对象的命令,而不采用其他命令对象吗?
这种方法也可以,不过相当于进行了“硬编码”到了命令对象中。而利用宏命令可以动态改变命令对象,显然宏命令更加优雅,也需要较少的新代码。
原文地址:https://www.cnblogs.com/dlvguo/p/9807327.html