軟件設計模式修煉 -- 組合模式


組合模式關注那些存在於葉子構件和容器構件的結構以及它們的組織形式,葉子構件中不能包含成員對象,容器構件中能夠包含成員對象,這些成員對象多是葉子構件對象,也多是容器構件對象。這些對象能夠構成一個樹形結構,組合模式是用面向對象的方法處理樹形結構。java


模式動機

在Windows操做系統的文件目錄結構包含文件和文件夾兩類對象,其中在文件夾能夠包含子文件夾,也能夠包含文件。文件夾是容器類,而不一樣類型的各類文件是成員類,也稱爲葉子類,一個文件夾也能夠做爲另外一個更大的文件夾的成員。組合模式描述瞭如何將容器對象和葉子對象進行遞歸組合,使得用戶在使用時無須對它們進行區分,能夠作到一致對待容器對象和葉子對象。算法


模式定義

組合多個對象造成樹形結構以表示「總體-部分」的結構層次。編程


模式結構

在這裏插入圖片描述

  1. Component(抽象構件)安全

    抽象構件能夠是接口或抽象類,爲葉子構件和容器構件對象聲明接口,在該角色中能夠包含全部子類共有行爲的聲明和實現。在抽象構件在定義了訪問及管理它的子構件的方法,如增長子構件、刪除子構件、獲取子構件等。ide

  2. Leaf(葉子構件)操作系統

    葉子構件在組合結構中表示葉子節點對象,葉子節點沒有子節點,實如今抽象構件中定義的行爲。對於訪問及管理子構件的方法,能夠經過異常等方式進行處理。設計

  3. Composite(容器構件)code

    容器構件在組合結構中表示容器節點對象,容器節點包含子節點,其子節點能夠是葉子節點,也能夠是容器節點,它提供一個集合用於存儲子節點,實如今抽象構件中定義的行爲,包括那些訪問及管理子構件的方法,在其業務方法中能夠遞歸調用其子節點的業務方法。對象

  4. Client(客戶類)blog

    客戶類是能夠經過抽象構件接口訪問和控制組合構件中的對象。


模式分析

組合模式的關鍵是定義一個抽象構件類,它既能夠表明葉子,也能夠表明容器,而客戶端針對該抽象構件類進行編程,無須知道它究竟是葉子仍是容器,能夠對其進行統一處理。

通常抽象構件類設計爲接口或抽象類,將全部子類共有方法聲明和實現放在抽象構件類中。對於客戶端編程,將針對抽象構件編程,而無須關心其具體子類是容器構件仍是葉子構件。

public abstract class Component {

    public abstract void add(Component c);
    public abstract void remove(Component c);
    public abstract Component getChild(int i);
    public abstract void operation();
}

繼承抽象構件的是葉子構件則典型代碼以下,葉子構件須要實現抽象構建類中聲明的全部方法,包括業務方法以及管理和訪問子構件的方法,可是葉子構件不包含子構件,所以在在客戶端調用葉子構件的子構件管理和訪問方法時需提供異常處理或錯誤提示。

public class Leaf extends Component {

    @Override
    public void add(Component c) {
        //異常處理或錯誤提示
    }

    @Override
    public void remove(Component c) {
        //異常處理或錯誤提示
    }

    @Override
    public Component getChild(int i) {
        //異常處理或錯誤提示
        return null;
    }

    @Override
    public void operation() {
        //實現代碼
    }
}

容器構件須要實現抽象構建類中聲明的全部方法,包括具體實現業務方法以及管理和訪問子構件的方法。因爲容器構件充當的是容器角色,包含成員構件,所以它將調用其成員構件的業務方法,使用遞歸算法,即在容器構件的operation()方法中遞歸調用其成員構件的operation()方法。

public class Composite extends Component {

    private ArrayList list = new ArrayList();

    @Override
    public void add(Component c) {
        list.add(c);
    }

    @Override
    public void remove(Component c) {
        list.remove(c);
    }

    @Override
    public Component getChild(int i) {
        return (Component) list.get(i);
    }

    @Override
    public void operation() {
        for (Object o : list) {
            ((Component) o).operation();
        }
    }
}

模式優缺點

組合模式優勢:

  1. 組合模式能夠清楚地定義分層次的複雜對象,表示對象的所有或部分層次,方便對層次結構進行控制
  2. 客戶端能夠一致的適用組合結構或其中單個對象,用戶沒必要關心本身處理的是單個對象仍是整個組合結構
  3. 定義了包含葉子對象和容器對象的類的層次結構,葉子對象能夠被組合成更復雜的容器對象,而這個容器對象又能夠被組合,這樣不斷遞歸下去,能夠造成複雜的樹形結構
  4. 更容易在組合體內加入對象構件,客戶端沒必要由於加入新的對象構件而更改原有代碼

組合模式缺點:

  1. 使設計變得更加抽象
  2. 增長新構件時可能會產生一些問題,很難對容器中的構件類型進行限制

模式適用環境

在如下狀況下可使用組合模式:

  1. 須要表示一個對象總體或部分層次,在具備總體和部分的層次結構中,但願忽略總體與部分的差別,一致地對待它們
  2. 客戶能忽略不一樣對象層次的變化,客戶端能夠針對抽象構件編程,無須關心對象層次結構的細節
  3. 對象的結構是動態且複雜程度不一致,但客戶須要一致地處理它們

透明組合模式與安全組合模式

組合模式根據抽象構件類的定義形式,又可分爲透明組合模式和安全組合模式

  1. 透明組合模式

    透明組合模式中,抽象構件Component中聲明全部用於管理成員對象的方法,這樣作的好處是確保全部構件類都有相同的接口。在客戶端看來,葉子對象與容器對象所提供的方法是一致的,客戶端能夠相同地對待全部的對象。缺點是不夠安全,由於葉子對象和容器對象在本質上是有區別的。

  2. 安全組合模式

    安全組合模式中抽象構件Component中沒有聲明任何用於管理成員對象的方法,而是在Composite類中聲明這些用於管理成員對象的方法。對於葉子對象,客戶端不可能調用到管理成員對象的方法。缺點是不夠透明,客戶端不能徹底針對抽象編程。

相關文章
相關標籤/搜索