JUNIT源码探秘(七):Junit代码分析之装饰模式
在Junit实现中,对于大部分测试代码的执行都是按照前文分析的执行过程,但同时在Junit中也提供对一个测试方法重复执行多次能力。而重复执行的过程中实际上他是把执行过程给分解成若干个相同的测试过程,也是说他的执行本质还是和单个测试方法的执行是一样的。直接使用Juint源码来说吧,Junit真正调用执行Junit测试代码是在TestCase这个类中;对于要重复多次执行一个测试方法时,则过继承Test的另一个接口类TestDecorator的实现类之一RepeatedTest来执行。而这完全是有个装饰模式。由其可以看出代理模式有以下几个角色
抽象构建角色(Component):给出一个抽象的接口,以规范准备接受附加责任的对象。相当于Junit源码中的Test。
具体的构建角色(ConcreteComponent):定义一个将要接受附加责任的类。相当于Junit源码中的TestCase。
装饰角色(Docorator):持有一个抽象构建(Component)角色的引用,并定义一个与抽象构件一致的接口。相当于Junit源码中的TestDecorator。
具体的装饰角色(ConcreteDecorator):负责给构建对象“贴上”附加的责任。相当于Junit源码中RepeatedTest类;
当然,如果Junit有其他功能需要扩展时,可以继续对装饰角色继续持续实现。由此可以看出装饰模式是动态地给一个对象添加一些额外的职责,也是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也是装饰来包裹真实的对象。增加功能来说,Decorator模式相比生成子类更为灵活。
利用Junit源码中的类的关系图大家可以继续看下装饰模式的关系
为了更明白的说明装饰模式,可以继续看下装饰模式各个角色的实现代码(为了易于理解装饰模式,在这块实现代码用一个简单的例子说明):
抽象构建角色(Component):
package com.wonew.mode;
public interface Component {
publicvoiddoSomething();
}
具体的构建角色(ConcreteComponent):
package com.wonew.mode;
public class ConcreteComponent implementsComponent{
publicvoiddoSomething(){
System.out.println("功能A……");
}
}
装饰角色(Docorator):
package com.wonew.mode;
public class Decorate implements Component{
privateComponent component;
publicDecorate(Component component) {
this.component = component;
}
publicvoiddoSomething() {
component.doSomething();
}
}
具体的装饰角色(ConcreteDecorator):
实现一:
package com.wonew.mode;
public class ConcreteDecorate1 extends Decorate
{
publicConcreteDecorate1(Component component)
{
super(component);
}
publicvoiddoSomething()
{
super.doSomething();
this.doAnotherDosomething();
}
privatevoiddoAnotherDosomething()
{
System.out.println("功能B");
}
}
实现二:
package com.wonew.mode;
public class ConcreteDecorate2 extends Decorate
{
publicConcreteDecorate2(Component component)
{
super(component);
}
publicvoiddoSomething()
super.doSomething();
this.doAnotherDosomething();
}
privatevoiddoAnotherDosomething()
{
System.out.println("功能C");
}
}
在具体的装饰角色中实现了两个具体的类,而此处正是装饰模式大的好处,装饰模式扩展的是对象的功能,不需要增加类的数量,而类继承扩展是类的功能,在继承的关系中,如果我们想增加一个对象的功能,我们只能通过继承关系,在子类中增加一个方法。
关于Junit使用装饰模式的代码,再次不再详细分析,有兴趣的同学可以根据上面的类图具体查看