设计模式---组合模式
設計模式---組合模式
- 什么是組合模式:Composite?
- 使用場景
- 代碼示例
- 組合模式模板
- 組合模式的安全性和透明性
- 總結
- 優缺點:
- 適用場景:
什么是組合模式:Composite?
計算機的文件系統中,一個文件夾中既可以放入文件也可以放入其他文件夾(子文件夾),所以文件夾和文件雖然是不同類型的對象,但它們都是可以被放入到文件夾中,可以統稱為"目錄條目"(directory entry)
在目錄條目中,我們把文件夾和文件當作同一對象看待。
對于這種將容器和內容作為同一種東西看待,在容器中既可以放入內容,也可以放入小容器,然后在那個小容器中,又可以繼續放入更小的容器,這樣就形成一種容器的遞歸結構(有點類似于俄羅斯套娃的感覺)
Composite模式就是創造出使容器與內容具有一致性的遞歸結構的模式。它將對象組合成樹型結構以表示"部分-整體"的層次結構,使得用戶對單個對象和組合對象的操作具有一致性
使用場景
在一個商品管理的系統中,管理商品樹是一個比較常見的基礎功能,假設這里有一個商品樹, 想要寫一個程序打印出類似的樹型結構:
這里有多個節點,可以把節點分成兩類:
一種是沒有子節點的葉子節點:夾克,襯衫等
一種是有子節點的容器節點:服務,女裝等
如果使用組合模式實現功能,我們會將葉子節點和容器節點當做一致的對象來處理,但實際二者之間還是有差別的,因為葉子節點不能添加子節點,而容器節點可以,所以我們為其定義一個抽象父類,這樣葉子節點和容器節點既能保證一致性,又可以有各自不同的實現
代碼示例
package com.chenpp.pattern.composite.reconfiguration;/*** @Description* @Author chenpp* @Date 2019/9/30 10:25*/ public abstract class Component {private String name = "";public Component(String name){this.name = name;}protected String getName(){return name;}protected abstract void printStruct(String prefix);/*** 向組合對象中加入組件對象* 葉子對象沒有該功能** */protected void addChild(Component component) {throw new UnsupportedOperationException("此對象不支持addChild該功能");}/*** 向組合對象中移除組件對象* 葉子對象沒有該功能** */protected void removeChild(Component component){throw new UnsupportedOperationException("此對象不支持removeChild該功能");} } package com.chenpp.pattern.composite.reconfiguration;/*** @Description* @Author chenpp* @Date 2019/9/30 10:27*/ public class Leaf extends Component {public Leaf(String name){super(name);}/**** 打印對應的葉子結構* @param prefix 前綴 實現向后縮進**/public void printStruct(String prefix){System.out.println(prefix + "-" + super.getName());} } package com.chenpp.pattern.composite.reconfiguration;/*** @Description* @Author chenpp* @Date 2019/9/30 10:25*/ public abstract class Component {private String name = "";public Component(String name){this.name = name;}protected String getName(){return name;}protected abstract void printStruct(String prefix);/*** 向組合對象中加入組件對象* 葉子對象沒有該功能** */protected void addChild(Component component) {throw new UnsupportedOperationException("此對象不支持addChild該功能");}/*** 向組合對象中移除組件對象* 葉子對象沒有該功能** */protected void removeChild(Component component){throw new UnsupportedOperationException("此對象不支持removeChild該功能");} } package com.chenpp.pattern.composite.reconfiguration;/*** @Description* @Author chenpp* @Date 2019/9/30 11:07* 使用組合模式重構*/ public class Client {public static void main(String[] args) {//組合對象 作為根節點Component root = new Composite("服裝");//組合對象Component composite1 = new Composite("夏裝");Component composite2 = new Composite("冬裝");//葉子節點Leaf leaf1 = new Leaf("裙子");Leaf leaf2 = new Leaf("背心");Leaf leaf3 = new Leaf("棉衣");root.addChild(composite1);root.addChild(composite2);composite1.addChild(leaf1);composite1.addChild(leaf2);composite2.addChild(leaf3);root.printStruct("");} }輸出結果:
組合模式模板
從示例代碼和組合模式的特點我們可以看出,一般組合模式會包含以下三種角色:
其模板如下:
public abstract class Component {protected abstract void doSomeOperation();/*** 向組合對象中加入組件對象* 葉子對象沒有該功能** */protected void addChild(Component component) {throw new UnsupportedOperationException("此對象不支持addChild該功能");}/*** 向組合對象中移除組件對象* 葉子對象沒有該功能** */protected void removeChild(Component component){throw new UnsupportedOperationException("此對象不支持removeChild該功能");} } public class Leaf extends Component {protected void doSomeOperation() {//TODO}} public class Composite extends Component {private List<Component> componentList = null;protected void doSomeOperation() {//TODO}@Overrideprotected void addChild(Component component) {if(componentList == null){componentList = new ArrayList<Component>();}componentList.add(component);}@Overrideprotected void removeChild(Component component) {if(componentList != null){componentList.remove(component);}} }這是組合模式的模板類圖:子組件的操作方法可以根據實際情況來定義
組合模式的安全性和透明性
組合模式中,Composite對象就像是一個容器,可以包含其他的Composite對象或者葉子對象。作為一個容器, 我們可以向其中添加或者刪除子對象(包括Leaf和Composite對象)
這樣在使用組合模式的時候就需要考慮對子組件的操作是在Component還是Composite中聲明?這就是對安全性和透明性之前的權衡。
安全性 : 從用戶使用角度上組合模式是否安全,如果是安全的,那么用戶在使用的時候就不會有發生誤操作的可能性,能訪問的都是支持的有意義的操作
透明性 : 用戶使用組件對象的時候是否需要區分到底是容器對象還是葉子對象, 如果是透明的,就不需要區分
透明性的實現:將操作子組件的方法定義在Component, 同時為了兼顧安全性,可以在Component中為這些方法提供默認實現 比方說拋出異常,默認的空實現或者定義成抽象方法。
不過這也違背了設計的單一原則
安全性的實現: 把操作子組件的方法定義在Composite
組合模式的核心思想是:讓用戶對葉子對象和組合對象的使用具有一致性
故而在安全性和透明性的取舍上,一般更傾向于透明性
總結
優缺點:
優點
缺點 : 很難限制組合中的組件類型
適用場景:
對于想表示對象的部分–整體的層次結構,比如樹型菜單,文件和文件夾的管理
參考資料
《研磨設計模式》
總結
以上是生活随笔為你收集整理的设计模式---组合模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ProtoBuf的使用以及原理分析
- 下一篇: 设计模式--装饰模式