组合模式
定义:
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得用户对单个对象和组合对象的使用具有一致性
构成:
Component:这是一个抽象角色,它给参加组合的对象规定一个接口。这个角色给出共有的接口和默认的行为。其实就我们的Test接口,它定义出run方法
Composite:实现共有接口并维护一个测试用例的集合,它就是复合测试用例TestSuite
Leaf:代表参加组合的对象,它没有下级子对象,仅定义出参加组合的原始对象的行为,其实就是单一的测试用例TestCase,它仅实现Test接口的方法
分类:
将管理子元素的方法定义在Composite类中;
将管理子元素的方法定义在Component接口中;
java代码实现:
将管理子元素的方法定义在Composite类中
public interface Component { public void doSomething(); }
public class Composite implements Component { private List<Component> list = new ArrayList<Component>(); public void add(Component component) { list.add(component); } public void remove(Component component) { list.remove(component); } public List<Component> getAll() { return list; } @Override public void doSomething() { for (Component component : list) { component.doSomething(); } } }
public class Leaf implements Component { public void doSomething() { System.out.println("dosomething"); } }
public class Client { public static void main(String[] args) { Component leaf1 = new Leaf(); Component leaf2 = new Leaf(); Composite composite = new Composite(); composite.add(leaf1); composite.add(leaf2); Composite composite2 = new Composite(); Component leaf3 = new Leaf(); composite2.add(composite); composite2.add(leaf3); composite2.doSomething(); } }
将管理子元素的方法定义在Component接口中
public interface Component { public void doSomething(); public void add(Component component); public void remove(Component component) ; public List<Component> getAll() ; }
public class Composite implements Component { private List<Component> list = new ArrayList<Component>(); public void add(Component component) { list.add(component); } public void remove(Component component) { list.remove(component); } public List<Component> getAll() { return list; } @Override public void doSomething() { for (Component component : list) { component.doSomething(); } } }
public class Leaf implements Component { public void doSomething() { System.out.println("dosomething"); } public void add(Component component) { } public List<Component> getAll() { return null; } public void remove(Component component) { } }
public class Client { public static void main(String[] args) { Component leaf1 = new Leaf(); Component leaf2 = new Leaf(); Composite composite = new Composite(); composite.add(leaf1); composite.add(leaf2); Composite composite2 = new Composite(); Component leaf3 = new Leaf(); composite2.add(composite); composite2.add(leaf3); composite2.doSomething(); } }
组合模式在junit3框架中的应用
public interface Test { public abstract void run(TestResult result); } public abstract class TestCase extends Assert implements Test { public void run(TestResult result) { result.run(this); } } public class TestSuite implements Test { private Vector fTests= new Vector(10); public void addTest(Test test) { fTests.addElement(test); } public void addTestSuite(Class testClass) { addTest(new TestSuite(testClass)); } public void run(TestResult result) { for (Enumeration e= tests(); e.hasMoreElements(); ) { if (result.shouldStop() ) break; Test test= (Test)e.nextElement(); runTest(test, result); } } public Enumeration tests() { return fTests.elements(); } }
TestSuit类中有一个属性fTests (Vector类型)中保存了其子测试用例,提供addTest方法来实现增加子对象TestCase,并且还提供testCount 和tests 等方法来操作子对象。最后通过run()方法实现对其子对象进行委托(delegate),最后还提供addTestSuite方法实现递归,构造成树形;
TestCase或者TestSuite都是对Test接口进行实现的。由于TestCase和TestSuit两者都符合Test接口,我们可以通过addTestSuite递归地将TestSuite再组合成TestSuite,这样将构成树形结构。所有开发者都能够创建他们自己的TestSuit。测试人员可创建一个组合了这些测试用例的TestSuit来运行它们所有的TestCase,形如:
public static Test suite() { TestSuite suite1 = new TestSuite("我的测试TestSuit1"); TestSuite suite2 = new TestSuite("我的测试TestSuit2"); suite1.addTestSuite(xxx.class); suite2.addTestSuite(xxx.class); suite1.addTest(suite2); return suite1; }
junit3中引入组合模式的好处
1)简化了JUnit的代码 JUnit可以统一处理组合结构TestSuite和单个对象TestCase。使JUnit开发变得简单容易,因为不需要区分部分和整体的区别,不需要写一些充斥着if else的选择语句;
2)定义了TestCase对象和TestSuite的类层次结构基本对象TestCase可以被组合成更复杂的组合对象TestSuite,而这些组合对象又可以被组合,如上个例子,这样不断地递归下去。在程序的代码中,任何使用基本对象的地方都可方便的使用组合对象,大大简化系统维护和开发;
3)使得更容易增加新的类型的TestCase;