命令模式:
将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化;对请求进行排队或记录请求日志...
Command模式告诉我们可以为一个操作(方法)生成一个对象并给出它的一个"execute(执行)"方法。
注意:这里都是一个。
命令模式的构成:
1、客户角色 : 创建一个具体命令对象,并确定其接收者
2、命令角色 : 声明一个给所有具体命令类的抽象接口。这是一个抽象角色,通常由一个接口或抽象类实现
3、具体角色 : 定义一个接收者和行为之间的弱耦合,实现execute方法,负责调用接收者的相应操作
4、请求者角色 : 负责调用命令对象执行请求
5、接收者角色 : 负责具体实施和执行一个请求
通过一个类比来方便我们的记忆:
当我们去饭店吃饭,点菜的时候,点菜就是一个命令,命令并不会自己去完成,而是有一个具体的接收者去完成的,点菜以后具体的实施是由厨师去完成的,那么厨师就是一个接收者,所以命令中要持有一个厨师的引用,而厨师并不依赖任何其他的对象。
代码实现:
命令的接口:
public interface Command {
public void doCommand(); //点菜
}
命令的实现:
public class ConcreteCommand implements Command {
private Receiver receiver; //接收者,在这里是厨师
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
public void doCommand() {
receiver.doAction();
}
}
接收者(厨师):
public class Receiver { //不依赖于其他任何的对象
public void doAction() {
System.out.println("do action");
}
}
请求者(客户端):
public class Client {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
command.doCommand();
}
}
对应于junit3.8中的代码实现
在junit3.8中定义了Test接口
public interface Test {
/**
* Counts the number of test cases that will be run by this test.
*/
public abstract int countTestCases();
/**
* Runs a test and collects its result in a TestResult instance.
*/
public abstract void run(TestResult result);
}
这里的Test接口就是Command的接口,run方法就是command中的doAction方法
TestCase是Test接口的抽象实现。它增加了一个测试名称属性,因为每一个TestCase在创建时都要有一个名称,如果一个测试失败了,便可识别出是哪个测试失败。
public abstract class TestCase extends Assert implements Test {
/**
* the name of the test case
*/
private String fName;
public void run(TestResult result) {
result.run(this);
}
}
这样测试人员,编写测试用例时,只需继承TestCase,来完成run方法即可,然后JUnit获得测试用例的请求,执行它的run方法,把测试结果记录在TestResult之中,目前可以暂且这样理解。
效果:
下面来考虑经过使用Command模式后给系统的架构带来了那些效果:
1、Command模式将实现请求的一方(TestCase开发)和调用一方(JUnit )进行解藕
2、Command模式使新的TestCase很容易加入,无需改变已有的类,只需继承TestCase类即可,这样方便了测试人员
3、Command模式可以将多个TestCase进行组合成一个复合命令,你将看到TestSuit就是它的复合命令,当然它使用了Composite模式
4、Command模式容易把请求的TestCase组合成请求队列,这样使接收请求的一方(Junit Fromwork),容易决定是否执行请求,一旦发现测试用例失败或者错误可以立刻停止进行报告
5、Command模式可以在需要的情况下,方便实现对请求的Undo和Redo,以及记录Log,这部分目前在JUnit中还没有实现,将来是很容易加入的。
缺点:
由于命令模式只能为一个操作(方法)生成一个对象并给出它的一个"execute(执行)"方法。
所以:10个操作就要生成10个对象,会造成类的膨胀的!!!而且没个类中只能有一个方法,然后由接收者去执行这个方法。
所以在Junit3.8框架中就引入了适配器模式,将在后文中详细阐述!