Command模式
Command模式只是封装了一个没有任何变量的函数.
- interface Command{ void Excute();}
- 具有强烈的分解功能的味道.把函数层面的任务提升到了类的层面(一个类仅仅是为了完成一个函数,而且没有该函数外的任何成员).
- 简单的Command
- 事件驱动的系统.
- Sensor(传感器).驱动者.只负责监听事件,并在事件发生后,调用绑定的Command的Excute方法.而不知道具体绑定的是什么样的Command.
- Command只负责执行具体的命令逻辑.
- 两者的绑定关系可以定义于系统主体之外(xml文件etc.)
- 事件驱动的系统.
- 事务操作.
- 解除了 从用户获取数据,验证并操作数据,业务对象本身的耦合关系.
- 时间上解耦. 立即执行Validate,而把Transaction对放在一个List中,之后再执行.(用于DB中的夜间执行场景).
- UnDo
- 给Command接口添加一个Undo方法.
- 很容易实现:知道如何去excute命令的代码和如何去undo命令的代码几乎类似.
- Active Object模式
-
public interface CommandEngine { void AddCommand(Command cmd); } public class RTCEngine : CommandEngine { private List<Command> Commands; public RTCEngine() { this.Commands = new List<Command>(); } public void AddCommand(Command cmd) { this.Commands.Add(cmd); } /// <summary> /// 执行Command队列中的所有命令,直至队列中不再含有任何的Command. /// </summary> public void Do() { while (this.Commands.Count > 0) { var cmd = Commands.First(); this.Commands.Remove(cmd); cmd.Excute(); } } }
1 public interface Command 2 { 3 void Excute(); 4 } 5 6 7 8 public class SleepCommand : Command 9 { 10 private long sleepTime; 11 12 private CommandEngine engine; 13 private Command callBack; 14 15 private bool start; 16 private long startTime; 17 18 public SleepCommand(long timeout, CommandEngine engine, Command callBack) 19 { 20 this.sleepTime = timeout; 21 this.engine = engine; 22 this.callBack = callBack; 23 24 this.start = false; 25 } 26 27 #region Command Members 28 29 /// <summary> 30 /// 执行,根据条件克隆自己或者添加CallBack命令到Engine中去. 31 /// </summary> 32 public void Excute() 33 { 34 long time = System.DateTime.Now.Ticks; 35 36 //如果还未启动,那么启动自身,同时将自己添加到Engine队列末尾. 37 if (!start) 38 { 39 this.start = true; 40 this.startTime = time; 41 engine.AddCommand(this); 42 } 43 //如果还没到唤醒时间,那么添加自己到Engine的队列末尾. 44 if (time - startTime < sleepTime) 45 { 46 engine.AddCommand(this); 47 } 48 else 49 { 50 //已经到唤醒时间,将CallBack命令添加到Engine的队列末尾. 51 engine.AddCommand(callBack); 52 } 53 } 54 55 #endregion 56 }
- 阻塞式多线程:当一个线程等待一个事件时,它通常使用一些OS调用来阻塞自己直到事件发生.
- RTC(run-to-completion):
- 每个Command实例都在下一个Command实例可以运行之前就运行完成了.
- 意味着Command实例不会阻塞.(如果等待的事件未到来,只是把自己放回到Engine中).
- Command实例一经运行就一定得完成.所有的Command实例可以共享一个运行时堆栈.(减少内存使用量).
-
总结. Command模式具有极其的简洁性.但可以用于DB的Transaction操作,设备控制,多线程核心,GUI的do/undo管理.
其有不符合OO范式的味道.对函数的关注超过了类.
[Agile Software Development(Principles,Patterns,and Pracitices)]