java合成模式之神奇的樹結構
什麼是合成模式
以下是互聯網的解釋。
合成模式屬於對象的結構模式,有時又叫做“部分——整體”模式。合成模式將對象組織到樹結構中,可以用來描述整體與部分的關系。合成模式可以使客戶端將單純元素與復合元素同等看待。
經常會出現有樹結構的情況 , 其中由單獨的對象或者單獨對象組成的合成對象組成 , 此時就需要利用一種方式來完成樹結構的構建工作 .
合成模式提供一個樹結構中所有對象的統一接口 , 規范樹中單獨對象和合成對象的構建過程 , 合成模式更像一個數據結構 .
合成模式的實現方式分為透明式和安全式 , 主要區別在於管理方法是在抽象構件中聲明, 還是直接在樹枝構件中定義.
- 透明式 , 管理方法在抽象構件中聲明 , 同時樹葉節點需要用平庸的方式實現管理方法
- 安全式 , 在樹枝構件中直接定義管理方法 , 這樣避免在樹葉構件中進行定義 .
設計模式和編程語言無關,但是二當傢的依然用Java語言去實戰舉例。
安全式合成模式
- 抽象構件(Component)角色:這是一個抽象角色,它給參加組合的對象定義出公共的接口及其默認行為,可以用來管理所有的子對象。合成對象通常把它所包含的子對象當做類型為Component的對象。在安全式的合成模式裡,構件角色並不定義出管理子對象的方法,這一定義由樹枝構件對象給出。
- 樹葉構件(Leaf)角色:樹葉對象沒有下級子對象,定義出參加組合的原始對象的行為。
- 樹枝構件(Composite)角色:代表參加組合的有下級子對象的對象,並給出樹枝構件對象的行為。
抽象構件(Component)角色
抽象構件聲明瞭葉子和樹枝都應該有的行為。
package com.secondgod.composite; /** * 抽象構件 * * @author 二當傢的白帽子 https://le-yi.blog.csdn.net/ */ public interface Component { /** * 輸出自身的名稱 */ void printStruct(String preStr); }
樹葉構件(Leaf)角色
樹葉不會再有下級。
package com.secondgod.composite; import java.text.MessageFormat; /** * 樹葉 * * @author 二當傢的白帽子 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)); } }
樹枝構件(Composite)角色
樹枝可以繼續長出樹枝或者樹葉,所以要有addChild方法。
package com.secondgod.composite; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; /** * 樹枝 * * @author 二當傢的白帽子 https://le-yi.blog.csdn.net/ */ public class Composite implements Component { /** * 用來存儲組合對象中包含的子組件對象 */ private List<Component> childComponents = new ArrayList<Component>(); /** * 組合對象的名字 */ private String name; public Composite(String name){ this.name = name; } /** * 聚集管理方法,增加一個子構件對象 * @param child 子構件對象 */ 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) { // 添加兩個空格,表示向後縮進兩個空格 preStr += " "; // 輸出當前對象的子對象 for (Component c : childComponents) { // 遞歸輸出每個子對象 c.printStruct(preStr); } } } }
使用
package com.secondgod.composite; /** * 測試 * * @author 二當傢的白帽子 https://le-yi.blog.csdn.net/ */ public class Client { public static void main(String[]args){ Composite root = new Composite("生物"); Composite c1 = new Composite("動物"); 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(""); } }
執行結果符合預期。
透明式合成模式
抽象構件(Component)角色
生長樹枝和樹葉的方法直接聲明在抽象構件裡。本例使用抽象類,其實也可以使用接口。
package com.secondgod.composite; /** * 抽象構件 * * @author 二當傢的白帽子 https://le-yi.blog.csdn.net/ */ public abstract class Component { /** * 輸出自身的名稱 */ public abstract void printStruct(String preStr); /** * 聚集管理方法,增加一個子構件對象 * @param child 子構件對象 */ public void addChild(Component child){ /** * 缺省實現,拋出異常,因為葉子對象沒有此功能 * 或者子組件沒有實現這個功能 */ throw new UnsupportedOperationException("對象不支持此功能"); } }
樹葉構件(Leaf)角色
透明式的葉子從實現抽象構件改成繼承抽象構件。如果抽象構件是接口,則需要平庸實現管理子構件的方法。
package com.secondgod.composite; import java.text.MessageFormat; /** * 樹葉 * * @author 二當傢的白帽子 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)); } }
樹枝構件(Composite)角色
透明式的樹枝也是從實現抽象構件改為繼承抽象構件,這主要跟抽象構件是抽象類還是接口有關。
package com.secondgod.composite; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; /** * 樹枝 * * @author 二當傢的白帽子 https://le-yi.blog.csdn.net/ */ public class Composite extends Component { /** * 用來存儲組合對象中包含的子組件對象 */ private List<Component> childComponents = new ArrayList<Component>(); /** * 組合對象的名字 */ private String name; public Composite(String name){ this.name = name; } /** * 聚集管理方法,增加一個子構件對象 * @param child 子構件對象 */ 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) { // 添加兩個空格,表示向後縮進兩個空格 preStr += " "; // 輸出當前對象的子對象 for (Component c : childComponents) { // 遞歸輸出每個子對象 c.printStruct(preStr); } } } }
使用
客戶端在使用時,變量可以都聲明為抽象構件。
package com.secondgod.composite; /** * 測試 * * @author 二當傢的白帽子 https://le-yi.blog.csdn.net/ */ public class Client { public static void main(String[]args){ Component root = new Composite("生物"); Component c1 = new Composite("動物"); 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(""); } }
可以看出,客戶端無需再區分操作的是樹枝對象(Composite)還是樹葉對象(Leaf)瞭;對於客戶端而言,操作的都是Component對象。
安全式和透明式
安全式:從客戶端使用合成模式上看是否更安全,如果是安全的,那麼就不會有發生誤操作的可能,能訪問的方法都是被支持的。
透明式:從客戶端使用合成模式上,是否需要區分到底是“樹枝對象”還是“樹葉對象”。如果是透明的,那就不用區分,對於客戶而言,都是Compoent對象,具體的類型對於客戶端而言是透明的,是無須關心的。因為無論樹葉還是樹枝,均符合一個固定的接口。
到底使用安全式還是透明式需要看需求,大傢看著辦吧。
以上就是java合成模式之神奇的樹結構的詳細內容,更多關於java合成模式的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Java結構型設計模式之組合模式詳解
- java實現Composite組合模式的實例代碼
- 一文帶你真正理解Java中的內部類
- Java使用MessageFormat應註意的問題
- Java設計模式之組合模式的示例詳解