Composite(組合)模式思維導圖


Composite(組合)模式思維導圖

描述

定義

將對象組合成樹形結構以表示“部分-整體”的層次結構。Composite使得用戶對單個對象和組合對象的使用具有一致性。

類型

對象結構型模式

UML類圖

Composite模式UML類圖

實現

主要角色

  • Component:抽象構件
    • 爲組合中的對象聲明接口。
    • 在適當的情況下,實現所有類共有接口的缺省行爲。
    • 聲明一個接口用於訪問和管理Component的子組件。
    • (可選)在遞歸結構中定義一個接口,用於訪問一個父部件,並在合適的情況下實現它。
  • Leaf:樹葉構件
    • 在組合中表示葉節點對象,葉節點沒有子節點。
    • 在組合中定義圖元對象的行爲。
  • Composite:樹枝構件
    • 定義有子部件的那些部件的行爲。
    • 存儲子部件。
    • 在Component接口中實現與子部件有關的操作。
  • Client:客戶端類
    • 通過Component接口操縱組合部件的對象。

安全模式 VS 透明模式

組合模式的實現根據所實現接口的區別分爲兩種形式:安全模式和透明模式。安全模式要求管理子組件的方法只出現在樹枝構件類中,而不出現在樹葉構件中。而透明模式要求所有的具體構件類,不論樹枝構件還是樹葉構件,均符合同一個固定的接口。

對於組合模式而言,在安全性和透明性上,會更看重透明性,畢竟組合模式的目的是:讓客戶端不再區分操作的是樹枝對象還是樹葉對象,而是以一個統一的方式來操作。而且對於安全性的實現,需要區分的是樹枝對象還是樹葉對象。有時候,需要將對象進行類型強行轉換,這種類型轉換必然是不夠安全的。

因此在使用組合模式的時候,建議多采用透明式的實現方式。

透明模式代碼示例

  • Component:抽象構件

      public abstract class Component {
      	public void operation();
    
      	// 安全模式中下面接口方法只位於組合構件中
      	public abstract void add(Component component);
      	public abstract void remove(Component component);
      	public abstract List<Component> getChildren();
      }
    
  • Leaf:樹葉構件

      public class Leaf extends Component {
      	public void operation() {
      		System.out.println("Leaf component");
      	}
      	public void add(Component component) {
      		throw new UnsupportedOperationException("對象不支持此功能");
      	}
      	public void remove(Component component) {
      		throw new UnsupportedOperationException("對象不支持此功能");
      	}
      	// 空實現
      	public List<Component> getChildren() {
      		return new ArrayList<Component>();
      	}
      }
    
  • Composite:樹枝構件

      public class Composite extends Component {
      	// 構件容器
      	private ArrayList<Component> componentArrayList = new ArrayList<Component>();
      	public void add(Component component) {
      		this.componentArrayList.add(component);
      	}
      	public void remove(Component component) {
      		this.componentArrayList.remove(component);
      	}
      	public List<Component> getChildren() {
      		return this.componentArrayList;
      	}
      	public operation() {
      		for (Component c: componentArrayList) {
      			c.operation();
      		}
      	}
      }
    
  • Client:客戶端類

      public class Client {
      	public static void main(String[] args) {
      		Composite root = new Composite();
      		Leaf leaf = new Leaf();
      		leaf.operation();
      		root.add(leaf);
      		root.operation();
      	}
      }
    

適用場景

  • 需要表示對象的部分-整體層次結構。
  • 希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。

優點

  • 簡化了客戶端代碼。Composite模式採用樹形結構來實現普遍存在的對象容器,從而將“一對多”的關係轉化爲“一對一”的關係,使得客戶代碼可以一致地處理對象和對象容器,無需關心處理的是單個的對象,還是組合的對象容器。
  • 對樹形結構的複雜對象容易控制。組合模式爲樹形結構的面向對象實現提供了一種靈活的解決方案,通過葉子對象和容器對象的遞歸組合,可以形成複雜的樹形結構,但對樹形結構的控制卻非常簡單。
  • 增加新構件很方便。無須對現有類庫進行任何修改,符合“開閉原則”。

缺點

  • 使得設計更加複雜,客戶端需要花更多時間理清類之間的層次關係。
  • 在增加新構件時很難對容器中的構件類型進行限制。在需要檢測組件類型時,不能依靠編譯期的類型約束來實現,必須在運行期間動態檢測。

相關模式

  • 通常部件-父部件連接用於Responsibility of Chain模式。
  • Decorator模式經常與Composite模式一起使用。當裝飾和組合一起使用時,它們通常有一個公共的父類。因此裝飾必須支持具有add、remove和getChildren操作的Component接口。
  • Flyweight讓你共享組件,但不再能引用他們的父部件。
  • (迭代器模式)Itertor可用來遍歷Composite。
  • Visitor將本來應該分佈在Composite和Leaf類中的操作和行爲局部化。
發佈了53 篇原創文章 · 獲贊 8 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章