java合成模式之神奇的樹結(jié)構(gòu)
什么是合成模式
以下是互聯(lián)網(wǎng)的解釋。
合成模式屬于對象的結(jié)構(gòu)模式,有時(shí)又叫做“部分——整體”模式。合成模式將對象組織到樹結(jié)構(gòu)中,可以用來描述整體與部分的關(guān)系。合成模式可以使客戶端將單純元素與復(fù)合元素同等看待。
經(jīng)常會(huì)出現(xiàn)有樹結(jié)構(gòu)的情況 , 其中由單獨(dú)的對象或者單獨(dú)對象組成的合成對象組成 , 此時(shí)就需要利用一種方式來完成樹結(jié)構(gòu)的構(gòu)建工作 .
合成模式提供一個(gè)樹結(jié)構(gòu)中所有對象的統(tǒng)一接口 , 規(guī)范樹中單獨(dú)對象和合成對象的構(gòu)建過程 , 合成模式更像一個(gè)數(shù)據(jù)結(jié)構(gòu) .
合成模式的實(shí)現(xiàn)方式分為透明式和安全式 , 主要區(qū)別在于管理方法是在抽象構(gòu)件中聲明, 還是直接在樹枝構(gòu)件中定義.
- 透明式 , 管理方法在抽象構(gòu)件中聲明 , 同時(shí)樹葉節(jié)點(diǎn)需要用平庸的方式實(shí)現(xiàn)管理方法
- 安全式 , 在樹枝構(gòu)件中直接定義管理方法 , 這樣避免在樹葉構(gòu)件中進(jìn)行定義 .
設(shè)計(jì)模式和編程語言無關(guān),但是二當(dāng)家的依然用Java語言去實(shí)戰(zhàn)舉例。
安全式合成模式
- 抽象構(gòu)件(Component)角色:這是一個(gè)抽象角色,它給參加組合的對象定義出公共的接口及其默認(rèn)行為,可以用來管理所有的子對象。合成對象通常把它所包含的子對象當(dāng)做類型為Component的對象。在安全式的合成模式里,構(gòu)件角色并不定義出管理子對象的方法,這一定義由樹枝構(gòu)件對象給出。
- 樹葉構(gòu)件(Leaf)角色:樹葉對象沒有下級(jí)子對象,定義出參加組合的原始對象的行為。
- 樹枝構(gòu)件(Composite)角色:代表參加組合的有下級(jí)子對象的對象,并給出樹枝構(gòu)件對象的行為。
抽象構(gòu)件(Component)角色
抽象構(gòu)件聲明了葉子和樹枝都應(yīng)該有的行為。
package com.secondgod.composite; /** * 抽象構(gòu)件 * * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/ */ public interface Component { /** * 輸出自身的名稱 */ void printStruct(String preStr); }
樹葉構(gòu)件(Leaf)角色
樹葉不會(huì)再有下級(jí)。
package com.secondgod.composite; import java.text.MessageFormat; /** * 樹葉 * * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/ */ public class Leaf implements Component { /** * 葉子對象的名字 */ private String name; public Leaf(String name) { this.name = name; } @Override public void printStruct(String preStr) { System.out.println(MessageFormat.format("{0}-{1}", preStr, name)); } }
樹枝構(gòu)件(Composite)角色
樹枝可以繼續(xù)長出樹枝或者樹葉,所以要有addChild方法。
package com.secondgod.composite; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; /** * 樹枝 * * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/ */ public class Composite implements Component { /** * 用來存儲(chǔ)組合對象中包含的子組件對象 */ private List<Component> childComponents = new ArrayList<Component>(); /** * 組合對象的名字 */ private String name; public Composite(String name){ this.name = name; } /** * 聚集管理方法,增加一個(gè)子構(gòu)件對象 * @param child 子構(gòu)件對象 */ public void addChild(Component child){ childComponents.add(child); } @Override public void printStruct(String preStr) { // 先把自己輸出 System.out.println(MessageFormat.format("{0}+{1}", preStr, name)); // 如果還包含有子組件,那么就輸出這些子組件對象 if (this.childComponents != null) { // 添加兩個(gè)空格,表示向后縮進(jìn)兩個(gè)空格 preStr += " "; // 輸出當(dāng)前對象的子對象 for (Component c : childComponents) { // 遞歸輸出每個(gè)子對象 c.printStruct(preStr); } } } }
使用
package com.secondgod.composite; /** * 測試 * * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/ */ public class Client { public static void main(String[]args){ Composite root = new Composite("生物"); Composite c1 = new Composite("動(dòng)物"); Composite c2 = new Composite("植物"); Leaf leaf1 = new Leaf("貓貓"); Leaf leaf2 = new Leaf("狗狗"); Leaf leaf3 = new Leaf("大樹"); Leaf leaf4 = new Leaf("小草"); root.addChild(c1); root.addChild(c2); c1.addChild(leaf1); c1.addChild(leaf2); c2.addChild(leaf3); c2.addChild(leaf4); root.printStruct(""); } }
執(zhí)行結(jié)果符合預(yù)期。
透明式合成模式
抽象構(gòu)件(Component)角色
生長樹枝和樹葉的方法直接聲明在抽象構(gòu)件里。本例使用抽象類,其實(shí)也可以使用接口。
package com.secondgod.composite; /** * 抽象構(gòu)件 * * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/ */ public abstract class Component { /** * 輸出自身的名稱 */ public abstract void printStruct(String preStr); /** * 聚集管理方法,增加一個(gè)子構(gòu)件對象 * @param child 子構(gòu)件對象 */ public void addChild(Component child){ /** * 缺省實(shí)現(xiàn),拋出異常,因?yàn)槿~子對象沒有此功能 * 或者子組件沒有實(shí)現(xiàn)這個(gè)功能 */ throw new UnsupportedOperationException("對象不支持此功能"); } }
樹葉構(gòu)件(Leaf)角色
透明式的葉子從實(shí)現(xiàn)抽象構(gòu)件改成繼承抽象構(gòu)件。如果抽象構(gòu)件是接口,則需要平庸實(shí)現(xiàn)管理子構(gòu)件的方法。
package com.secondgod.composite; import java.text.MessageFormat; /** * 樹葉 * * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/ */ public class Leaf extends Component { /** * 葉子對象的名字 */ private String name; public Leaf(String name) { this.name = name; } @Override public void printStruct(String preStr) { System.out.println(MessageFormat.format("{0}-{1}", preStr, name)); } }
樹枝構(gòu)件(Composite)角色
透明式的樹枝也是從實(shí)現(xiàn)抽象構(gòu)件改為繼承抽象構(gòu)件,這主要跟抽象構(gòu)件是抽象類還是接口有關(guān)。
package com.secondgod.composite; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; /** * 樹枝 * * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/ */ public class Composite extends Component { /** * 用來存儲(chǔ)組合對象中包含的子組件對象 */ private List<Component> childComponents = new ArrayList<Component>(); /** * 組合對象的名字 */ private String name; public Composite(String name){ this.name = name; } /** * 聚集管理方法,增加一個(gè)子構(gòu)件對象 * @param child 子構(gòu)件對象 */ public void addChild(Component child){ childComponents.add(child); } @Override public void printStruct(String preStr) { // 先把自己輸出 System.out.println(MessageFormat.format("{0}+{1}", preStr, name)); // 如果還包含有子組件,那么就輸出這些子組件對象 if (this.childComponents != null) { // 添加兩個(gè)空格,表示向后縮進(jìn)兩個(gè)空格 preStr += " "; // 輸出當(dāng)前對象的子對象 for (Component c : childComponents) { // 遞歸輸出每個(gè)子對象 c.printStruct(preStr); } } } }
使用
客戶端在使用時(shí),變量可以都聲明為抽象構(gòu)件。
package com.secondgod.composite; /** * 測試 * * @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/ */ public class Client { public static void main(String[]args){ Component root = new Composite("生物"); Component c1 = new Composite("動(dòng)物"); Component c2 = new Composite("植物"); Component leaf1 = new Leaf("貓貓"); Component leaf2 = new Leaf("狗狗"); Component leaf3 = new Leaf("大樹"); Component leaf4 = new Leaf("小草"); root.addChild(c1); root.addChild(c2); c1.addChild(leaf1); c1.addChild(leaf2); c2.addChild(leaf3); c2.addChild(leaf4); root.printStruct(""); } }
可以看出,客戶端無需再區(qū)分操作的是樹枝對象(Composite)還是樹葉對象(Leaf)了;對于客戶端而言,操作的都是Component對象。
安全式和透明式
安全式:從客戶端使用合成模式上看是否更安全,如果是安全的,那么就不會(huì)有發(fā)生誤操作的可能,能訪問的方法都是被支持的。
透明式:從客戶端使用合成模式上,是否需要區(qū)分到底是“樹枝對象”還是“樹葉對象”。如果是透明的,那就不用區(qū)分,對于客戶而言,都是Compoent對象,具體的類型對于客戶端而言是透明的,是無須關(guān)心的。因?yàn)闊o論樹葉還是樹枝,均符合一個(gè)固定的接口。
到底使用安全式還是透明式需要看需求,大家看著辦吧。
以上就是java合成模式之神奇的樹結(jié)構(gòu)的詳細(xì)內(nèi)容,更多關(guān)于java合成模式的資料請關(guān)注腳本之家其它相關(guān)文章!
- 詳解Java構(gòu)建樹結(jié)構(gòu)的公共方法
- Java實(shí)現(xiàn)遞歸查詢樹結(jié)構(gòu)的示例代碼
- java樹結(jié)構(gòu)stream工具類的示例代碼詳解
- JAVA使用hutool工具實(shí)現(xiàn)查詢樹結(jié)構(gòu)數(shù)據(jù)(省市區(qū))
- JAVA如何轉(zhuǎn)換樹結(jié)構(gòu)數(shù)據(jù)代碼實(shí)例
- JAVA后臺(tái)轉(zhuǎn)換成樹結(jié)構(gòu)數(shù)據(jù)返回給前端的實(shí)現(xiàn)方法
- Java實(shí)現(xiàn)簡單樹結(jié)構(gòu)
- java后端操作樹結(jié)構(gòu)的案例代碼
相關(guān)文章
springboot基于Redis發(fā)布訂閱集群下WebSocket的解決方案
這篇文章主要介紹了springboot基于Redis發(fā)布訂閱集群下WebSocket的解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Java的ThreadPoolExecutor業(yè)務(wù)線程池詳細(xì)解析
這篇文章主要介紹了Java線程池ThreadPoolExecutor詳細(xì)解析,任務(wù)剛開始進(jìn)來的時(shí)候就創(chuàng)建核心線程,核心線程滿了會(huì)把任務(wù)放到阻塞隊(duì)列,阻塞隊(duì)列滿了之后才會(huì)創(chuàng)建空閑線程,達(dá)到最大線程數(shù)之后,再有任務(wù)進(jìn)來,就只能執(zhí)行拒絕策略了,需要的朋友可以參考下2024-01-01詳解在Spring3中使用注解(@Scheduled)創(chuàng)建計(jì)劃任務(wù)
本篇文章主要介紹了詳解在Spring3中使用注解(@Scheduled)創(chuàng)建計(jì)劃任務(wù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03SpringBoot實(shí)現(xiàn)子類的反序列化示例代碼
這篇文章主要給大家介紹了關(guān)于SpringBoot實(shí)現(xiàn)子類的反序列化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用SpringBoot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08MyBatis版本升級(jí)導(dǎo)致OffsetDateTime入?yún)⒔馕霎惓栴}復(fù)盤
這篇文章主要介紹了MyBatis版本升級(jí)導(dǎo)致OffsetDateTime入?yún)⒔馕霎惓栴}復(fù)盤,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08IDEA中使用Docker Compose容器編排的實(shí)現(xiàn)
這篇文章主要介紹了IDEA中使用Docker Compose容器編排的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Java多種經(jīng)典排序算法(含動(dòng)態(tài)圖)
排序算法是老生常談的了,但是在面試中也有會(huì)被問到,例如有時(shí)候,在考察算法能力的時(shí)候,不讓你寫算法,就讓你描述一下,某個(gè)排序算法的思想以及時(shí)間復(fù)雜度或空間復(fù)雜度。我就遇到過,直接問快排的,所以這次我就總結(jié)梳理一下經(jīng)典的十大排序算法以及它們的模板代碼2021-04-04java設(shè)計(jì)模式之外觀模式(Facade)
這篇文章主要為大家詳細(xì)介紹了java設(shè)計(jì)模式之外觀模式Facade的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01