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