在面向过程的编程中,类似于树形结构或者文件目录结构,一般使用递归的方式进行处理,而在面向过程中,对于这类问题抽象处理为组合模式。
组合模式(Composite Pattern)有时候又叫做部分-整体模式,它在处理树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。组合模式让你可以优化处理递归或分级数据结构。
对于组合模式的角色也比较简单,我们试着对文件目录结构进行分析,在文件目录结构中至少有两种结构,一种是文件,一种是目录。对于这两个角色最大的区别就是,一个是叶子节点,一个是树枝结构。那么也可以把这两个对象抽象成一个接口类。这样分析后文件目录结构就有三个角色,即叶子(叶子组件),树枝 (组合组件),抽象结构(抽象构件接口)。下面对每个角色具体分析
抽象构件角色(Component):它为组合中的对象声明接口,也可以为共有接口实现缺省行为。
树叶构件角色(Leaf):在组合中表示叶节点对象——没有子节点,实现抽象构件角色声明的接口。
树枝构件角色(Composite):在组合中表示分支节点对象——有子节点,实现抽象构件角色声明的接口;存储子部件。
Client(客户端)
–通过Component接口控制组合部件的对象
各个角色之间关系如下:
如图上图所示:一个Composite实例可以像一个简单的Leaf实例一样,可以把它传递给任何使用Component的方法或者对象,并且它表现的就像是一个Leaf一样。使用组合模式使得这个设计结构非常灵活。
各个角色代码实现如下:
抽象构件角色(Component):
public interface Component
{
public void doSomething();
}
树叶构件角色(Leaf):
public class Leaf implements Component
{
@Override
public void doSomething()
{
System.out.println("执行方法");
}
}
树枝构件角色(Composite):
public class Composite implements Component
{
private List list = newArrayList();
public void add(Component component)
{
list.add(component);
}
public void remove(Component component)
{
list.remove(component);
}
public List getAll()
{
return this.list;
}
public void doSomething()
{
for(Component component : list)
{
component.doSomething();
}
}
}
Client(客户端)
public static void main(String[] args)
{
Component leaf1 = new Leaf();
Component leaf2 = new Leaf();
Composite comp1 = new Composite();
comp1.add(leaf1);
comp1.add(leaf2);
Component leaf3 = new Leaf();
Component leaf4 = new Leaf();
Composite comp2 = new Composite();
comp2.add(comp1);
comp2.add(leaf3);
comp2.add(leaf4);
comp2.doSomething();
}
这样对组合模式就基本分析完成,继续接着看下在Junit组合模式是最样实现的呢?
在Junit中有连个重要的概念,一个是TestCase一个是TestSuite;TestSuite是一个测试集合,一个TestSuite中可以包含一个或者多个TestSuite,当然也可以一个或者多个TestCase,而这两个对象都继承与Test接口。这样一分析,Test接口相当于组合模式中的抽象构件角色(Component),TestSuite相当于树枝构件角色(Composite),TestCase相当于树叶构件角色(Leaf)。接着我们对具体代码分析看看这块是否满足组合模式。
Test接口类:
public interface Test {
public abstract int countTestCases();
public abstract void run(TestResult result);
}
TestSuite实现:
public int countTestCases() {
int count= 0;
for (Enumeration e= tests(); e.hasMoreElements(); ) {
Test test= (Test)e.nextElement();
count= count + test.countTestCases();
}
return count;
}
public void run(TestResult result) {
for (Enumeration e= tests(); e.hasMoreElements(); ) {
if (result.shouldStop() )
break;
Test test= (Test)e.nextElement();
runTest(test, result);
}
}
TestCase实现
public int countTestCases() {
return 1;
}
public void run(TestResult result) {
result.run(this);
}
根据代码分析,Junit使用Composite模式后简化了JUnit的代码,JUnit可以统一处理组合结构TestSuite和单个对象TestCase。使JUnit开发变得简单容易,因为不需要区分部分和整体的区别,不需要写一些充斥着if else的选择语句。
另外,通过对TestCase对象和TestSuite的类层次结构基本对象的定义,TestCase可以被组合成更复杂的组合对象TestSuite,而这些组合对象又可以被组合,这样不断地递归下去。在程序的代码中,任何使用基本对象的地方都可方便的使用组合对象,大大简化系统维护和开发。
原文转自:http://blog.sina.com.cn/s/blog_6e0d94750101653y.html