二十三種設(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);
}
}