組合模式

前言

組合模式也是結構型模式的一種。node

目錄

1、定義

組合模式也叫合成模式,或者稱部分-總體模式,主要是用來描述部分與總體的關係。算法

將對象組合成樹形結構以表示 「部分-總體」 的層次結構,使得用戶對單個對象和組合對象的使用具備一致性。安全

這裏有兩個關鍵點:一個是用樹形結構來分層,另外一個是經過統一對待來簡化操做markdown

2、模式原理分析

模式主要包含三個角色數據結構

  • 抽象組件:定義須要實現的統一操做。ide

  • 組合節點:表明一個能夠包含多個節點的複合對象,意味着在它下面還能夠有其餘組合節點或葉子節點。this

  • 葉子節點:表明一個原子對象,意味着在它下面不會有其餘節點了。spa

    //抽象組件 public abstract class Component{ public abstract void operation(); } //葉子節點 public class Leaf extends Component{ @Override public void operation() { //葉子節點的操做放這裏 } } //組合節點 public class Node extends Component { private List myChildren; //存放子節點列表 @Override public void operation() { for (Component component: myChildren) { component.operation(); } } public List getAllMyChildren(){ return this.myChildren; } }code

結合上面的組合模式模板代碼,能大概瞭解出組合模式封裝瞭如下變化component

  • 葉子節點和組合節點之間的區別

  • 真實的數據結構,樹形?網狀?

  • 遍歷真實結構的算法,這裏不必定非要for循環遍歷

  • 結構所使用的一些策略,好比用來彙總的數據

例如建立一個能夠生成樹形對象功能 (AbstractNode抽象組件中,組合使用的方法都放到了該類,這種稱組合模式的透明模式,運行期可能拋異常。還有一種是安全模式,例如上面的模板代碼,父類沒有子類有的方法,將葉子節點和樹枝節點完全分開。)

//1.定義一個抽象組件 AbstractNode,其中定義節點能夠作的操做有:判斷是否爲根節點、獲取節點 id、獲取節點關聯父節點 id、設置 id、設置父 id、增長、刪除節點和獲取子節點。
public abstract class AbstractNode {
    public abstract boolean isRoot();
    public abstract int getId();
    public abstract int getParentId();
    public abstract void setId(int id);
    public abstract void setParentId(int parentId);
    public abstract void add(AbstractNode abstractNode);
    public abstract void remove(AbstractNode g);
    public abstract AbstractNode getChild(int i);
}
//2.建立組合節點 Node,繼承自 AbstractNode 實現定義的 8 種接口方法,其中 List 對象 children 用於存放子節點列表。
public class Node extends AbstractNode {
    private List<AbstractNode> children;
    private int id;
    private int pid;
    public Node() {
        children = new ArrayList<AbstractNode>();
    }
    @Override
    public boolean isRoot() {
        return -1 == pid;
    }
    @Override
    public int getId() {
        return id;
    }

    @Override
    public int getParentId() {
        return pid;
    }

    @Override
    public void setId(int id) {
        this.id = id;
    }

    @Override
    public void setParentId(int parentId) {
        this.pid = parentId;
    }

    public void add(AbstractNode c) {
        c.setParentId(this.pid+children.size());
        c.setId(c.getParentId()+1);
        children.add(c);
    }

    public void remove(AbstractNode c) {
        children.remove(c);
    }

    public AbstractNode getChild(int i) {
        return children.get(i);
    }

}
//3.建立葉子節點 Leaf,一樣繼承自 AbstractNode,重寫 8 種接口方法,不過,由於葉子節點不能新增和刪除節點,因此添加和刪除方法不支持,而且獲取子節點方法也應該爲空
public class Leaf extends AbstractNode {

    private int id;
    private int pid;
    @Override
    public boolean isRoot() {
        return false;
    }

    @Override
    public int getId() {
        return this.id;
    }

    @Override
    public int getParentId() {
        return this.pid;
    }

    @Override
    public void setId(int id) {
        this.id = id;
    }

    @Override
    public void setParentId(int parentId) {
        this.pid  = parentId;
    }

    @Override
    public void add(AbstractNode abstractNode) {
        throw new UnsupportedOperationException("這個是葉子節點,沒法增長");
    }
    
    @Override
    public void remove(AbstractNode g) {
        throw new UnsupportedOperationException("這個是葉子節點,沒法刪除");
    }

    @Override
    public AbstractNode getChild(int i) {
        return null;
    }
}
複製代碼

場景類

public class Client{
   public static void main(String[] args) {
        AbstractNode rootNode = new Node();
        rootNode.setId(0);
        rootNode.setParentId(-1);
        AbstractNode node1 = new Node();
        node1.add(new Leaf());
        node1.add(new Leaf());
        rootNode.add(new Leaf());
        rootNode.add(new Leaf());
        rootNode.add(node1);

        System.out.println(node1.getId());
   }

}
複製代碼

3、使用場景

  • 維護和展現部分-總體關係的場景,如樹形菜單、文件和文件夾管理

  • 統一處理一個結構中的多個對象

  • 只要是樹形結構,就能夠考慮組合模式

4、優勢

  • 高層模塊調用簡單

  • 清晰定義分層結構

  • 快速新增節點,提高組合靈活性

5、缺點

  • 難以限制節點類型

  • 對依賴致使原則破壞

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息