Java實(shí)現(xiàn)23種設(shè)計(jì)模式(七):組合模式

二十三種設(shè)計(jì)模式分類

設(shè)計(jì)模式三大分類.jpg

一、概述

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

優(yōu)點(diǎn)

  • 組合模式使得客戶端代碼可以一致地處理單個對象和組合對象,無須關(guān)心自己處理的是單個對象,還是組合對象,這簡化了客戶端代碼;
  • 更容易在組合體內(nèi)加入新的對象,客戶端不會因?yàn)榧尤肓诵碌膶ο蠖脑创a,滿足“開閉原則”;

缺點(diǎn)

  • 設(shè)計(jì)較復(fù)雜,客戶端需要花更多時間理清類之間的層次關(guān)系;
  • 不容易限制容器中的構(gòu)件;
  • 不容易用繼承的方法來增加構(gòu)件的新功能;

場景

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


二、實(shí)現(xiàn)

1. 結(jié)構(gòu)圖

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

  • 抽象構(gòu)件(Component)角色:它的主要作用是為樹葉構(gòu)件和樹枝構(gòu)件聲明公共接口,并實(shí)現(xiàn)它們的默認(rèn)行為。在透明式的組合模式中抽象構(gòu)件還聲明訪問和管理子類的接口;在安全式的組合模式中不聲明訪問和管理子類的接口,管理工作由樹枝構(gòu)件完成。
  • 樹葉構(gòu)件(Leaf)角色:是組合中的葉節(jié)點(diǎn)對象,它沒有子節(jié)點(diǎn),用于實(shí)現(xiàn)抽象構(gòu)件角色中 聲明的公共接口。
  • 樹枝構(gòu)件(Composite)角色:是組合中的分支節(jié)點(diǎn)對象,它有子節(jié)點(diǎn)。它實(shí)現(xiàn)了抽象構(gòu)件角色中聲明的接口,它的主要作用是存儲和管理子部件,通常包含Add()Remove()GetChild()等方法。
  • 透明方式:在該方式中,由于抽象構(gòu)件聲明了所有子類中的全部方法,所以客戶端無須區(qū)別樹葉對象和樹枝對象,對客戶端來說是透明的。但其缺點(diǎn)是:樹葉構(gòu)件本來沒有 Add()Remove()GetChild() 方法,卻要實(shí)現(xiàn)它們(空實(shí)現(xiàn)或拋異常),這樣會帶來一些安全性問題。
透明式組合模式
  • 安全方式:在該方式中,將管理子構(gòu)件的方法移到樹枝構(gòu)件中,抽象構(gòu)件和樹葉構(gòu)件沒有對子對象的管理方法,這樣就避免了上一種方式的安全性問題,但由于葉子和分支有不同的接口,客戶端在調(diào)用時要知道樹葉對象和樹枝對象的存在,所以失去了透明性。
安全式組合模式

PS:UML結(jié)構(gòu)圖可以參考,例子實(shí)現(xiàn)并不根據(jù)UML圖來完成,靈活實(shí)現(xiàn)即可;

2. 透明式實(shí)現(xiàn)

  • 抽象節(jié)點(diǎn)類
package cn.missbe.model.composite;

/**
 * Copyright (c) 2020.
 * Email: love1208tt@foxmail.com
 *
 * @author lyg  2020/4/22 下午1:21
 * description:
 * 組合模式,適用于樹狀結(jié)構(gòu)
 **/

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);
}
  • 分支節(jié)點(diǎn)
package cn.missbe.model.composite;

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

/**
 * Copyright (c) 2020.
 * Email: love1208tt@foxmail.com
 *
 * @author lyg  2020/4/22 下午1:21
 * description:
 * Composite 組合子結(jié)點(diǎn)
 **/

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);
        }
    }
}
  • 葉子節(jié)點(diǎn)
package cn.missbe.model.composite;

/**
 * Copyright (c) 2020.
 * Email: love1208tt@foxmail.com
 * @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: love1208tt@foxmail.com
 * @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);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容