Java描述设计模式(10):组合模式
本文源碼:GitHub·點(diǎn)這里 || GitEE·點(diǎn)這里
一、生活場(chǎng)景
1、文件系統(tǒng)
下圖是常見(jiàn)的計(jì)算機(jī)文件系統(tǒng)的一部分。
文件系統(tǒng)是一個(gè)樹(shù)結(jié)構(gòu),樹(shù)上長(zhǎng)有節(jié)點(diǎn)。樹(shù)的節(jié)點(diǎn)有兩種:
- 樹(shù)枝節(jié)點(diǎn)
即文件夾,有內(nèi)部樹(shù)結(jié)構(gòu),在圖中涂有顏色;
- 樹(shù)葉節(jié)點(diǎn)
另一種是文件,即樹(shù)葉節(jié)點(diǎn),沒(méi)有內(nèi)部樹(shù)結(jié)構(gòu)。
2、打印文件樹(shù)結(jié)構(gòu)
public class C01_InScene {public static void main(String[] args) {File file = new File("F:\\tree") ;fileTree(file, 0);}private static void fileTree(File file, int floor) {// 判斷是否存在if (file.exists()) {if (floor > 0) {// 循環(huán)打空格for (int i = 0; i < floor; i++) {System.out.print(" ");}}if (file.isDirectory()) {System.out.println("+" + file.getName());// 列出所有文件及文件夾File[] files = file.listFiles();if (null != files) {// 循環(huán)遞歸for (File dirFile : files) {fileTree(dirFile, floor + 1);}}} else {System.out.println("-" + file.getName());}}} }執(zhí)行效果:+代表文件夾,-代表文件。
+tree+dir1+dir2-dir2Leaf.txt-leaf1.txt-leaf2.txt-OneLeaf.txt-TwoLeaf.txt3、組合模式描述
組合模式屬于對(duì)象的結(jié)構(gòu)模式,有時(shí)又叫做“部分——整體”模式。組合模式將對(duì)象組織到樹(shù)結(jié)構(gòu)中,可以用來(lái)描述整體與部分的關(guān)系。組合模式可以使客戶(hù)端將單純?cè)嘏c復(fù)合元素同等看待。
二、組合模式-安全式
1、基礎(chǔ)概念
安全式的組合模式要求管理聚集的方法只出現(xiàn)在樹(shù)枝構(gòu)件類(lèi)中,而不出現(xiàn)在樹(shù)葉構(gòu)件類(lèi)中。涉及到三個(gè)角色:
- 抽象構(gòu)件(Component)角色
它給組合的對(duì)象定義出公共的接口及其默認(rèn)行為,可以用來(lái)管理所有的子對(duì)象。組合對(duì)象通常把它所包含的子對(duì)象當(dāng)做類(lèi)型為Component的對(duì)象。在安全式的組合模式里,構(gòu)件角色并不定義出管理子對(duì)象的方法,這一定義由樹(shù)枝構(gòu)件對(duì)象給出。
- 樹(shù)葉構(gòu)件(Leaf)角色
樹(shù)葉對(duì)象是沒(méi)有下級(jí)子對(duì)象的對(duì)象,定義出參加組合的原始對(duì)象的行為。
- 樹(shù)枝構(gòu)件(Composite)角色
代表參加組合的有下級(jí)子對(duì)象的對(duì)象。樹(shù)枝構(gòu)件類(lèi)給出所有的管理子對(duì)象的方法,如add()、remove()以及getChild()。
2、模式圖解
3、源代碼實(shí)現(xiàn)
public class C02_Security_Model {public static void main(String[] args) {Composite root = new Composite("服裝");Composite composite1 = new Composite("男裝");Leaf manCoat = new Leaf("上衣");Leaf manBottom = new Leaf("下衣");composite1.addChild(manCoat);composite1.addChild(manBottom);Composite composite2 = new Composite("女裝");Leaf leaf1 = new Leaf("鞋子");Leaf leaf2 = new Leaf("帽子");root.addChild(leaf1);root.addChild(leaf2);root.addChild(composite1);root.addChild(composite2);root.printStruct("");} } // 抽象構(gòu)件角色類(lèi) interface Component {/** 輸出組件自身的名稱(chēng)*/void printStruct(String preStr); } // 樹(shù)枝構(gòu)件角色類(lèi) class Composite implements Component{// 用來(lái)存儲(chǔ)組合對(duì)象中包含的子組件對(duì)象private List<Component> childComponents = new ArrayList<Component>();// 輸出對(duì)象的名稱(chēng)private String name;// 構(gòu)造方法,傳入組合對(duì)象的名字public Composite (String name){this.name = name;}/*** 聚集管理方法,增加一個(gè)子構(gòu)件對(duì)象* @param child 子構(gòu)件對(duì)象*/public void addChild(Component child){childComponents.add(child);}/*** 聚集管理方法,刪除一個(gè)子構(gòu)件對(duì)象* @param index 子構(gòu)件對(duì)象的下標(biāo)*/public void removeChild(int index){childComponents.remove(index);}/*** 聚集管理方法,返回所有子構(gòu)件對(duì)象*/public List getChild(){return childComponents ;}/*** 輸出對(duì)象的自身結(jié)構(gòu)* @param preStr 前綴,主要是按照層級(jí)拼接空格,實(shí)現(xiàn)向后縮進(jìn)*/@Overridepublic void printStruct(String preStr) {//先輸出自己System.out.println(preStr+"+"+this.name);//如果還包含有子組件,那么就輸出這些子組件對(duì)象if (this.childComponents != null){//添加兩個(gè)空格,表示向后縮進(jìn)兩個(gè)空格preStr = preStr+" ";//輸出當(dāng)前的子對(duì)象:使用函數(shù)遞歸的原理for (Component c : childComponents) {c.printStruct(preStr);}}} } class Leaf implements Component{// 輸出葉子對(duì)象的名稱(chēng)private String name;// 構(gòu)造方法,傳入葉子對(duì)象的名稱(chēng)public Leaf (String name){this.name = name ;}/*** 輸出葉子對(duì)象的結(jié)構(gòu),葉子對(duì)象沒(méi)有子對(duì)象,也就是輸出葉子對(duì)象的名字* @param preStr 前綴,主要是按照層級(jí)拼接的空格,實(shí)現(xiàn)向后縮進(jìn)*/@Overridepublic void printStruct(String preStr) {System.out.println(preStr+"-"+name);} }- 輸出結(jié)果
三、組合模式-透明式
1、概念圖解
與安全式的組合模式不同的是,透明式的組合模式要求所有的具體構(gòu)件類(lèi),不論樹(shù)枝構(gòu)件還是樹(shù)葉構(gòu)件,均符合一個(gè)固定接口。
2、源代碼實(shí)現(xiàn)
public class C03_Transparent_Model {public static void main(String[] args) {Component1 root = new Composite1("服裝");Component1 c1 = new Composite1("男裝");Component1 c2 = new Composite1("女裝");Component1 leaf1 = new Leaf1("襯衫");Component1 leaf2 = new Leaf1("夾克");Component1 leaf3 = new Leaf1("裙子");Component1 leaf4 = new Leaf1("套裝");root.addChild(c1);root.addChild(c2);c1.addChild(leaf1);c1.addChild(leaf2);c2.addChild(leaf3);c2.addChild(leaf4);root.printStruct("");} } abstract class Component1 {/*** 輸出組件自身的名稱(chēng)*/public abstract void printStruct(String preStr);// 聚集管理方法,增加一個(gè)子構(gòu)件對(duì)象public void addChild(Component1 child){/*** 缺省實(shí)現(xiàn),拋出異常,因?yàn)槿~子對(duì)象沒(méi)有此功能* 或者子組件沒(méi)有實(shí)現(xiàn)這個(gè)功能*/throw new UnsupportedOperationException("對(duì)象不支持此功能");}// 聚集管理方法,刪除一個(gè)子構(gòu)件對(duì)象public void removeChild(int index){/*** 缺省實(shí)現(xiàn),拋出異常,因?yàn)槿~子對(duì)象沒(méi)有此功能* 或者子組件沒(méi)有實(shí)現(xiàn)這個(gè)功能*/throw new UnsupportedOperationException("對(duì)象不支持此功能");}// 聚集管理方法,返回所有子構(gòu)件對(duì)象public List<Component1> getChild(){/*** 缺省實(shí)現(xiàn),拋出異常,因?yàn)槿~子對(duì)象沒(méi)有此功能* 或者子組件沒(méi)有實(shí)現(xiàn)這個(gè)功能*/throw new UnsupportedOperationException("對(duì)象不支持此功能");} } class Composite1 extends Component1 {// 用來(lái)存儲(chǔ)組合對(duì)象中包含的子組件對(duì)象private List<Component1> childComponents = new ArrayList<Component1>();// 輸出對(duì)象名稱(chēng)private String name ;public Composite1 (String name){this.name = name;}/*** 聚集管理方法,增加一個(gè)子構(gòu)件對(duì)象* @param child 子構(gòu)件對(duì)象*/public void addChild(Component1 child){childComponents.add(child);}/*** 聚集管理方法,刪除一個(gè)子構(gòu)件對(duì)象* @param index 子構(gòu)件對(duì)象的下標(biāo)*/public void removeChild(int index){childComponents.remove(index);}// 聚集管理方法,返回所有子構(gòu)件對(duì)象public List<Component1> getChild(){return childComponents ;}/*** 輸出對(duì)象的自身結(jié)構(gòu)* @param preStr 前綴,主要是按照層級(jí)拼接空格,實(shí)現(xiàn)向后縮進(jìn)*/@Overridepublic void printStruct(String preStr) {// 首先輸出自己名稱(chēng)System.out.println(preStr+"+"+this.name);// 如果還包含有子組件,那么就輸出這些子組件對(duì)象preStr = preStr + " ";if (this.childComponents != null) {// 添加兩個(gè)空格,表示向后縮進(jìn)for (Component1 c : childComponents) {遞歸輸出每個(gè)子對(duì)象c.printStruct(preStr);}}} } class Leaf1 extends Component1 {private String name;public Leaf1 (String name){this.name = name;}/*** 輸出葉子對(duì)象的結(jié)構(gòu),葉子對(duì)象沒(méi)有子對(duì)象,也就是輸出葉子對(duì)象的名字* @param preStr 前綴,主要是按照層級(jí)拼接的空格,實(shí)現(xiàn)向后縮進(jìn)*/@Overridepublic void printStruct(String preStr) {System.out.println(preStr+"-"+name);} }四、JDK中應(yīng)用
1、HashMap結(jié)構(gòu)圖
2、分層結(jié)構(gòu)
- interface Map
- class AbstractMap implements Map
- HashMap extends AbstractMap implements Map
- interface Map.Entry
- Node implements Map.Entry
3、源代碼
- 存儲(chǔ)葉子節(jié)點(diǎn)
- 存儲(chǔ)樹(shù)枝節(jié)點(diǎn)
五、源代碼地址
GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent總結(jié)
以上是生活随笔為你收集整理的Java描述设计模式(10):组合模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: TACACS +和RADIUS比较
- 下一篇: 计算方法太牛了,留着以后教孩子!!!