樹形結構在日常生活中是非常常見的,比如組織機構的這幾,軟件菜單的設計等,這些屬性結構,他們的葉子節點和父節點在行為上基本是一致的。只是在父節點上可能又包含了子節點。這類應用在軟件設計中,如果更好的來實現呢?這樣我們就引出了下面對于組合模式的簡單介紹:
組合模式(Composite)是整體與部分的關系,一個典型的應用就是樹型結構,組合模式可以抽象出三種角色,分別為抽象構建角色(Component)、樹枝構建角色(Composite)、樹葉構建角色(Leaf).
抽象構件角色Component:它為組合中的對象聲明接口,也可以為共有接口實現缺省行為。
樹葉構件角色Leaf:在組合中表示葉節點對象——沒有子節點,實現抽象構件角色聲明的接口。
樹枝構件角色Composite:在組合中表示分支節點對象——有子節點,實現抽象構件角色聲明的接口;存儲子部件。?
下面簡單的從原理圖來理解這個組合模式:

然后應用到了具體的實力,我簡單的舉例,比如現在我們的年級,在專業分流之前我們四個班級的,電氣6、7、8、9班,然后通過一個Composite類對這四個班級的人數的統計,實例如下:
首先設計的是一個年級接口,定義了一個getCount方法獲得這個年級所屬班級的人數,從而達到一個一級一級節點的遍歷,班級通過實現統一的接口,調用者對單一對象和組合對象的操作具有一致性。
~~~
package com.designpattern.composite;
public interface Grade {
public int getCount();
}
~~~
然后分別寫了四個班級的代碼:
~~~
package com.designpattern.composite;
public class ElectricalClass6 implements Grade {
@Override
public int getCount() {
return 53;
}
}
~~~
~~~
package com.designpattern.composite;
public class ElectricalClass7 implements Grade {
@Override
public int getCount() {
return 68;
}
}
~~~
~~~
package com.designpattern.composite;
public class ElectricalClass8 implements Grade {
@Override
public int getCount() {
return 70;
}
}
~~~
~~~
package com.designpattern.composite;
public class ElectricalClass9 implements Grade {
@Override
public int getCount() {
return 69;
}
}
~~~
緊接著寫了一個Composite類,也實現這個年級的接口,同時實現年級Grade接口里面聲明所有的用來管理子類對象的方法,以達到對年級Grade接口的最大化。目的就是為了使客戶看來在接口層次上樹葉和分支沒有區別,達到一個對于實現的透明度。
~~~
package com.designpattern.composite;
import java.util.ArrayList;
import java.util.List;
public class Composite implements Grade {
private List list = new ArrayList();
public Composite add(Grade grade) {
list.add(grade);
return this;
}
public Grade getChild(int i) {
return (Grade) list.get(i);
}
@Override
public int getCount() {
int count = 0;
for (int i = 0; i < list.size(); i++) {
Grade grade = (Grade) list.get(i);
count += grade.getCount();
}
return count;
}
public Composite remove(Grade grade) {
list.remove(grade);
return this;
}
}
~~~
同時這里的add和romove方法返回this指針,這樣襲用的dom4j的設計思想,操作的時候可以反復的中這個方法返回對象繼續進行想要的操作,同時在這里的Composite類和Class*類實現的是統一接口,這樣實現了功能的一致性,調用起來更顯得方便,如下:
~~~
composite.add(new ElectricalClass6()).add(new ElectricalClass7());
~~~
最后通過客戶端的調用體現了組合方法的實用性:
~~~
package com.designpattern.composite;
public class Client {
public static void main(String[] args) {
Composite grade = new Composite();
ElectricalClass6 class6 = new ElectricalClass6();
ElectricalClass7 class7 = new ElectricalClass7();
ElectricalClass8 class8 = new ElectricalClass8();
ElectricalClass9 class9 = new ElectricalClass9();
grade.add(class6).add(class7);
System.out.println("電氣6班和電氣7班的人數:" + grade.getCount());
grade.add(class8);
System.out.println("電氣6班和電氣7班和電氣8班的人數:" + grade.getCount());
grade.remove(class6);
System.out.println("電氣7班和電氣8班的人數:" + grade.getCount());
System.out.println("電氣7班的人數:" + grade.getChild(0).getCount());
System.out.println("電氣7班的人數:" + grade.remove(class8).getCount());
}
}
~~~
輸出結構測試:
~~~
電氣6班和電氣7班的人數:121
電氣6班和電氣7班和電氣8班的人數:191
電氣7班和電氣8班的人數:138
電氣7班的人數:68
電氣7班的人數:68
~~~
使用組合模式能夠提供比使用集成關系更靈活的功能,并且可以靈活的組合子對象和父對象之間的關系,從而使客戶端的調用簡單,客戶端可以一致的使用組合結構或其中單個對象,用戶就不比關系自己處理的是單個對象還是整個組合結構,這樣大大的減少了客戶端的代碼。
同時組合模式使得向集合添加新類型的組建變得容易,只要這些組建提供一個相似的變成接口即可,但這也是他的缺點,因為這種做法很難限制某個類。
- 前言
- 前言(目錄、源碼、資料)
- (一)簡單工廠模式(SimpleFatory)
- (二)工廠方法模式(FactoryMethod)
- (三)抽象工廠模式(AbstractFactory)
- (四)創建者模式(Builder)
- (五)原型模式(Prototype)
- (六)單例模式(Singleton)
- (七)外觀模式(Facade)
- (八)適配器模式(Adapter)
- (九)代理模式(Proxy)
- (十)裝飾模式(Decorator)
- (十一)橋模式(birdge)
- (十二)組合模式(Composite)
- (十三)享元模式(Flyweight)
- (十四)模板方法模式(Template)
- (十五)觀察者模式(Observer)
- (十六)狀態模式(State)