Java實現23種設計模式(七):組合模式

二十三種設計模式分類

設計模式三大分類.jpg


一、概述

組合(Composite)模式的定義:有時又叫作部分-整體模式,它是一種將對象組合成樹狀的層次結構的模式,用來表示“部分-整體”的關係,使用戶對單個對象和組合對象具有一致的訪問性。
將對象組合成樹形結構以表示"部分-整體"的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。

優點

  • 組合模式使得客戶端代碼可以一致地處理單個對象和組合對象,無須關心自己處理的是單個對象,還是組合對象,這簡化了客戶端代碼;
  • 更容易在組合體內加入新的對象,客戶端不會因爲加入了新的對象而更改源代碼,滿足“開閉原則”;

缺點

  • 設計較複雜,客戶端需要花更多時間理清類之間的層次關係;
  • 不容易限制容器中的構件;
  • 不容易用繼承的方法來增加構件的新功能;

場景

部分、整體場景,如樹形菜單,文件、文件夾的管理。


二、實現

1. 結構圖

組合模式包含以下主要角色:

  • 抽象構件(Component)角色:它的主要作用是爲樹葉構件和樹枝構件聲明公共接口,並實現它們的默認行爲。在透明式的組合模式中抽象構件還聲明訪問和管理子類的接口;在安全式的組合模式中不聲明訪問和管理子類的接口,管理工作由樹枝構件完成。
  • 樹葉構件(Leaf)角色:是組合中的葉節點對象,它沒有子節點,用於實現抽象構件角色中 聲明的公共接口。
  • 樹枝構件(Composite)角色:是組合中的分支節點對象,它有子節點。它實現了抽象構件角色中聲明的接口,它的主要作用是存儲和管理子部件,通常包含Add()Remove()GetChild()等方法。
  • 透明方式:在該方式中,由於抽象構件聲明瞭所有子類中的全部方法,所以客戶端無須區別樹葉對象和樹枝對象,對客戶端來說是透明的。但其缺點是:樹葉構件本來沒有 Add()Remove()GetChild() 方法,卻要實現它們(空實現或拋異常),這樣會帶來一些安全性問題。

透明式組合模式

  • 安全方式:在該方式中,將管理子構件的方法移到樹枝構件中,抽象構件和樹葉構件沒有對子對象的管理方法,這樣就避免了上一種方式的安全性問題,但由於葉子和分支有不同的接口,客戶端在調用時要知道樹葉對象和樹枝對象的存在,所以失去了透明性。

安全式組合模式

PS:UML結構圖可以參考,例子實現並不根據UML圖來完成,靈活實現即可;

2. 透明式實現

  • 抽象節點類
package cn.missbe.model.composite;

/**
 * Copyright (c) 2020.
 * Email: [email protected]
 *
 * @author lyg  2020/4/22 下午1:21
 * description:
 * 組合模式,適用於樹狀結構
 **/

public abstract class AbstractNode {
    String name;

    AbstractNode(String name) {
        this.name = name;
    }

    protected abstract void add(AbstractNode node);

    protected abstract void remove(AbstractNode node);

    public abstract void display(int depth);
}
  • 分支節點
package cn.missbe.model.composite;

import java.util.ArrayList;
import java.util.List;

/**
 * Copyright (c) 2020.
 * Email: [email protected]
 *
 * @author lyg  2020/4/22 下午1:21
 * description:
 * Composite 組合子結點
 **/

public class BranchNodeComposite extends AbstractNode {
    private List<AbstractNode> children = new ArrayList<>();

    BranchNodeComposite(String name) {
        super(name);
    }

    @Override
    public void add(AbstractNode node) {
        children.add(node);
    }

    @Override
    public void remove(AbstractNode node) {
        children.remove(node);
    }

    @Override
    public void display(int depth) {
        for (int i = 0; i < depth; i++) {
            System.out.print("----");
        }
        System.out.println(name);
        for (AbstractNode c : children) {
            c.display(depth + 1);
        }
    }
}
  • 葉子節點
package cn.missbe.model.composite;

/**
 * Copyright (c) 2020.
 * Email: [email protected]
 * @author lyg  2020/4/22 下午1:21
 * description:
 **/

public class LeafNode extends AbstractNode {

    LeafNode(String name) {
        super(name);
    }

    @Override
    protected void add(AbstractNode node) {
        System.out.println("cannot add..");
    }

    @Override
    protected void remove(AbstractNode node) {
        System.out.println("cannot remove..");
    }

    @Override
    public void display(int depth) {
        for (int i = 0; i < depth; i++) {
            System.out.print("----");
        }
        System.out.println(name);
    }
}
  • Main主類
package cn.missbe.model.composite;

/**
 * Copyright (c) 2020.
 * Email: [email protected]
 * @author lyg  2020/4/22 下午1:21
 * description:
 * 組合模式
 **/

public class Main {
    public static void main(String[] args) {
        AbstractNode root = new BranchNodeComposite("root");

        BranchNodeComposite chapter1 = new BranchNodeComposite("chapter1");
        chapter1.add(new LeafNode("LeafNode C"));
        chapter1.add(new LeafNode("LeafNode D"));
        root.add(chapter1);

        root.add(new LeafNode("LeafNode A"));
        root.add(new LeafNode("LeafNode B"));

        BranchNodeComposite chapter2 = new BranchNodeComposite("chapter2");
        chapter2.add(new LeafNode("LeafNode C"));
        chapter2.add(new LeafNode("LeafNode D"));
        root.add(chapter2);

        root.display(0);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章