特别注意Client中的
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker(command);
个人理解,这两块大的区别是Invoker调用的是一个借口类(当然在实际中可以也可以不是),在识别Invoker时注意调用的对象是否是一个接口对象。两外,命令模式各个角色之间的关系如下图所示。
Client和Invoker之间是一种弱关联的依赖关系。
在Junit为什么要适用命令模式呢?Junit中使用命令模式有什么好处呢?
先看看在Junit中为什么要使用命令模式,在这我们先看看Junit的执行过程的时序图,启动一次执行时,TestRunner先解析加载后,然后通过TestSuite、TestCase中的run方法继续解析成一个个Junit的测试方法(testcase),紧接着通过TestResult调用TestCase中的执行方法,通过TestCase中的runBare方法终调我们自己写的测试代码(含有testXXX的测试方法)。
通过对Junit代码的分析,TestRunner相当于命令模式中的客户(Client)角色,在TestRunner中main方法和doRun方法中的实现和命令模式中的Client的代码实现非常相似,具体如下
public static void main(String args[]) {
TestRunner aTestRunner= new TestRunner();
try {
TestResult r= aTestRunner.start(args);
//在start方法通过调用返回doRun方法
} catch(Exception e) {
System.err.println(e.getMessage());
System.exit(EXCEPTION_EXIT);
}
}
public TestResult doRun(Test suite, boolean wait) {
TestResult result= createTestResult();
result.addListener(fPrinter);
long startTime= System.currentTimeMillis();
suite.run(result);
long endTime= System.currentTimeMillis();
long runTime= endTime-startTime;
fPrinter.print(result, runTime);
pause(wait);
return result;
}
而命令(Command)角色是Junit中的TestCase(继承Test)。
具体命令(ConcreteCommand)是我们所写的测试方法,比如testXXX等所在的类
具体请求者(Invoker)则是TestResult,通过TestResult调用run方法,进而调用执行方法,
在Junit真正执行调用测试用例testcase则是在Junit中TestCase真正实现后的执行,所有说接收者(Receiver)接收者是TestCase,TestCase在命令模式中充当了多个角色,当然这块也可以在加一个类TestRun实现测试测试执行。但不知作者为什么要直接在TestCase中实现测试代码的终执行?
后我们再说说在这块用命令模式有什么好处?
我理解在这块大的好处是,解耦了具体命令者(我们自己写的testXXX方法)和TestCase,两外,实现了测试执行者TestRUnner和命令接受者TestResult的耦合,是命令请求和命令执行的对象分割。
另外补充一点,对于大多数请求-响应模式的功能,比较适合使用命令模式,正如命令模式定义说的那样,命令模式对实现记录日志、撤销操作等功能比较方便。