在面向過程的編程中,類似于樹形結構或者文件目錄結構,一般使用遞歸的方式進行處理,而在面向過程中,對于這類問題抽象處理為組合模式。
組合模式(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