設計模式《組合模式》
引言
上一節說了中介者模式,這話我們們說說組合模式。這個模式主要是用來表示具有“整體—部分”關係的層次結構。
示例地址
類圖
定義
將物件組合成樹形結構以表示“部分-整體”的層次結構,使得使用者對單個物件和組合物件的使用具有一致性。
使用場景
表示物件的部分-整體層次結構時。
從一個整體中能夠獨立出部分模組或功能的場景。
背景故事
我們去服裝市場,看看服裝的分類,服裝下面有男裝、女裝。男裝下面有包含短褲、襯衫,女裝下面包含裙子、小腳褲。按照我們一半的寫法,可以這樣寫。
一般寫法
1. 子節點
/**
* 子節點
*
* @author 512573717@qq.com
* @created 2018/8/2 上午11:43.
*/
public class ChildNode {
private String nodeName;
public ChildNode(String nodeName) {
this.nodeName = nodeName;
}
public void getNickname(String pre) {
System.out.println(pre + "-" + nodeName);
}
}
2. 父節點
/**
* 父節點
*
* @author 512573717@qq.com
* @created 2018/8/2 下午2:00.
*/
public class ParentNode {
private List<ChildNode> mLeafList = new ArrayList<>();
private List<ParentNode> mParentList = new ArrayList<>();
private String nodeName;
public ParentNode(String nodeName) {
this.nodeName = nodeName;
}
public void addParent(ParentNode parent) {
mParentList.add(parent);
}
public void addLeaf(ChildNode leaf) {
mLeafList.add(leaf);
}
public void getNickname(String pre) {
System.out.println(pre + nodeName);
//然後新增一個空格,表示向後縮排一個空格,輸出自己包含的葉子物件
pre += " ";
for (ChildNode leaf : mLeafList) {
leaf.getNickname(pre);
}
//輸出當前物件的子物件了
for (ParentNode c : mParentList) {
//遞迴輸出每個子物件
c.getNickname(pre);
}
}
}
3. Client
//定義所有的組合物件
ParentNode root = new ParentNode("服裝");
ParentNode c1 = new ParentNode("男裝");
ParentNode c2 = new ParentNode("女裝");
//定義所有的葉子物件
ChildNode leaf1 = new ChildNode("襯衣");
ChildNode leaf2 = new ChildNode("夾克");
ChildNode leaf3 = new ChildNode("裙子");
ChildNode leaf4 = new ChildNode("套裝");
//按照樹的結構來組合組合物件和葉子物件
root.addParent(c1);
root.addParent(c2);
c1.addLeaf(leaf1);
c1.addLeaf(leaf2);
c2.addLeaf(leaf3);
c2.addLeaf(leaf4);
//呼叫根物件的輸出功能來輸出整棵樹
root.getNickname("");
4. Result
服裝
男裝
-襯衣
-夾克
女裝
-裙子
-套裝
5. 存在缺點
需要知道那個是子節點,那個是父節點。然後按照對應的節點去新增。區別對待組合物件和葉子物件,不僅讓程式變得複雜,還對功能的擴充套件也帶來不便。
組合模式實現
1. 抽象節點類
/**
* 節點抽象類
*
* @author 512573717@qq.com
* @created 2018/8/2 下午2:17.
*/
public abstract class Node {
//節點名字
protected String nodeName;
public Node(String nodeName) {
this.nodeName = nodeName;
}
public void setNodeName(String nodeName) {
this.nodeName = nodeName;
}
// 列印節點名字
public abstract void getNodeName(String prefix);
//新增節點
public void addNode(Node node) {
}
//刪除節點
public void removeNode(Node node) {
}
//查詢節點
public void getIndexNode(int index) {
}
}
2. 定義父節點
/**
* 父節點
*
* @author 512573717@qq.com
* @created 2018/8/2 下午2:43.
*/
public class ParentNode extends Node {
private List<Node> mParents = null;
public ParentNode(String nodeName) {
super(nodeName);
}
@Override
public void getNodeName(String prefix) {
System.out.println(prefix+nodeName);
if (this.mParents != null) {
prefix +=" ";
for (Node c : mParents) {
//遞迴輸出每個子物件
c.getNodeName(prefix);
}
}
}
@Override
public void addNode(Node parent) {
if (mParents == null) {
mParents = new ArrayList<Node>();
}
mParents.add(parent);
}
}
3. 定義子節點
/**
* 子節點
*
* @author 512573717@qq.com
* @created 2018/8/2 下午2:25.
*/
public class ChildNode extends Node {
public ChildNode(String nodeName) {
super(nodeName);
}
@Override
public void getNodeName(String prefix) {
System.out.println(prefix+"-"+ nodeName);
}
}
4. Client
Node root = new ParentNode("服裝");
Node c1 = new ParentNode("男裝");
Node c2 = new ParentNode("女裝");
//定義所有的葉子物件
Node leaf1 = new ChildNode("襯衣");
Node leaf2 = new ChildNode("夾克");
Node leaf3 = new ChildNode("裙子");
Node leaf4 = new ChildNode("套裝");
//按照樹的結構來組合組合物件和葉子物件
root.addNode(c1);
root.addNode(c2);
c1.addNode(leaf1);
c1.addNode(leaf2);
c2.addNode(leaf3);
c2.addNode(leaf4);
//呼叫根物件的輸出功能來輸出整棵樹
root.getNodeName("");
組合模式的2種實現方式
安全性實現
如果把管理子元件的操作定義在ParentNode中,那麼客戶在使用葉子物件的時候,就不會發生使用新增子元件或是刪除子元件的操作了,因為壓根就沒有這樣的功能,這種實現方式是安全的。
透明性實現
如果把管理子元件的操作定義在Node中,那麼客戶端只需要面對Node,而無需關心具體的元件型別,這種實現方式就是透明性的實現。上面的示例就是透明性的。
總結
通過使用組合模式,把一個“部分-整體”的層次結構表示成了物件樹的結構,這樣一來,客戶端就無需再區分操作的是組合物件還是葉子物件了,對於客戶端而言,操作的都是元件物件。
參考連結
相關文章
- 【設計模式】組合模式設計模式
- 設計模式-組合模式設計模式
- 設計模式:組合模式設計模式
- js設計模式–組合模式JS設計模式
- js設計模式--組合模式JS設計模式
- 設計模式系列 – 組合模式設計模式
- javascript設計模式組合模式JavaScript設計模式
- 設計模式(十三):組合模式設計模式
- PHP 設計模式之組合模式PHP設計模式
- GoLang設計模式20 - 組合模式Golang設計模式
- 設計模式【11】-- 搞定組合模式設計模式
- 【C++設計模式】組合模式C++設計模式
- 徒手擼設計模式-組合模式設計模式
- 極簡設計模式-組合模式設計模式
- 設計模式系列之「組合模式」設計模式
- 大話設計模式—組合模式設計模式
- 軟體設計模式————(組合模式)設計模式
- 23種設計模式之組合模式設計模式
- 《Head First 設計模式》:組合模式設計模式
- Java設計模式之(十)——組合模式Java設計模式
- 【趣味設計模式系列】之【組合模式】設計模式
- javascript設計模式 之 7組合模式JavaScript設計模式
- 設計模式系列7--組合模式設計模式
- 設計模式漫談之組合模式設計模式
- C#設計模式之組合模式C#設計模式
- c#設計模式_全部部分模式_組合模式C#設計模式
- 《設計模式四》觀察、組合、享元模式設計模式
- [C++設計模式] composite 組合模式C++設計模式
- 設計模式之組合模式(Composite)分享設計模式
- 設計模式 | 組合模式及典型應用設計模式
- Java設計模式學習08——組合模式Java設計模式
- 《設計模式》 - 7. 組合模式( Composite )設計模式
- 設計模式之組合模式---Composite Pattern設計模式
- 設計模式(十四、十五)----結構型模式之組合模式設計模式
- JavaScript設計模式之策略模式【組合委託】JavaScript設計模式
- 設計模式(十)——組合模式(HashMap原始碼解析)設計模式HashMap原始碼
- 每天一個設計模式之組合模式設計模式
- C#設計模式-組合模式(Composite Pattern)C#設計模式