ACTIVE OBJECT 模式(转)
ACTIVE OBJECT 模式——《敏捷软件开发 原则、模式与实践(c#版)》第21章
想法很简单。考虑代码清单1-1和代码清单1-2。ActiveObjectEngine 对象维护了一个 ICommand 对象的链表。用户可以向该引擎增加新的命令,或者调用 Run()。Run() 函数只是遍历链表,执行并去除每个命令。
代码清单1-1
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace ActiveObject
{
public class ActiveObjectEngine
{
ArrayList itsCommands = new ArrayList();
public void AddCommand(ICommand aCommand)
{
itsCommands.Add(aCommand);
}
public void Run()
{
while (itsCommands.Count > 0)
{
ICommand c = (ICommand)itsCommands[0];
itsCommands.RemoveAt(0);
c.Execute();
}
}
}
}
代码清单1-2
{
void Execute();
}
考虑一下代码清单1-3中的测试用例。它创建了一个SleepCommand 对象。其中它向 SleepCommand 的构造函数中传了一个1,000ms的延迟。接着把 SleepCommand 对象放入到 ActiveObjectEngine 中。调用了 Run() 后,它将等待指定的毫秒数。
代码清单1-3
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
namespace ActiveObject
{
[TestFixture]
public class TestSleepCommand
{
private class WakeUpCommand : ICommand
{
public bool executed = false;
public void Execute()
{
this.executed = true;
}
}
[Test]
public void TestSleep()
{
WakeUpCommand wakeup = new WakeUpCommand();
ActiveObjectEngine e = new ActiveObjectEngine();
SleepCommand c = new SleepCommand(1000, e, wakeup);
e.AddCommand(c);
DateTime start =DateTime.Now;
e.Run();
DateTime stop = DateTime.Now;
double sleepTime = (stop - start).TotalMilliseconds;
Assert.IsTrue(sleepTime >= 1000,
string.Format("SleepTime {0} expected > 1000",sleepTime.ToString()));
Assert.IsTrue(sleepTime <= 1100,
string.Format("SleepTime {0} expected < 1100", sleepTime.ToString()));
Assert.IsTrue(wakeup.executed, "Command Executed");
}
}
}
我们来仔细看看这个测试用例。SleepCommand 的构造函数有 3 个参数。
第一个:是延迟的毫秒数;
第二个:是在其中运行该命令的ActiveObjectEngine 对象;
第三个:是一个名为 wakeup 的另一个命令对象。
测试的意图是 SleepCommand 会等待指定数目的毫秒,然后执行 wakeup 命令。
代码清单1-4展示了 SleepCommand 的实现。在执行时,SleepCommand 检查自己以前是否已经执行过,如果没有,就记录下开始时间。如果没有过延迟时间,就把自己再加到 ActiveObjectEngine 中。如果过了延迟时间,就把 wakeup 命令对象加到 ActiveObjectEngine 中。
代码清单1-4
using System;
using System.Collections.Generic;
using System.Text;
namespace ActiveObject
{
public class SleepCommand : ICommand
{
private ICommand wakeupCommand = null;
private ActiveObjectEngine engine = null;
private long SleepTime = 0;
private DateTime startTime;
private bool started = false;
public SleepCommand(long milliSeconds, ActiveObjectEngine e,
ICommand wakeupCommand)
{
this.SleepTime = milliSeconds;
this.engine = e;
this.wakeupCommand = wakeupCommand;
}
public void Execute()
{
DateTime currentTime = DateTime.Now;