標籤:
合成模式合成模式把部分和整體關係用樹結構表示,是屬於對象的結構模式。合成模式要對組合的對象進行管理,所以在一定位置給予對象的相關管理方法,如:add(),remove()等.合成模式中對象的管理有兩種方案。1.安全方式:此方式只允許樹枝構件有對象的管理方法。2.透明方式:此方式只允許樹枝和樹葉都有對象的管理方法,但樹葉對象中的管理方法無實際意義。
一.UML
二.組成部分抽象構件:抽象組合對象的公用行為介面樹葉構件:樹葉對象,沒有下級子物件樹枝構件:樹枝對象,樹枝對象可以包含一個或多個其他樹枝或樹葉對象
三.代碼例子:我以一個超市購物為例(一)、安全方式1.
抽象物品(抽象構件)
package com.eekq.structure.composite.security;/* * 抽象構件,物品 * */public interface IRes { /**購物買單,示意性的商業方法*/ public void pay();}
2.
單一物品(樹葉構件)
package com.eekq.structure.composite.security;public class SingleResImpl implements IRes { /**物品名稱*/ private String name; /**價錢*/ private float money; public SingleResImpl(String name, float money) { this.name = name; this.money = money; } public void pay() { System.out.println("購買了一件物品["+getName()+"],價錢是[" + getMoney()+"]元"); } public float getMoney() { // TODO 自動產生方法存根 returnthis.money; } public String getName() { // TODO 自動產生方法存根 return this.name; } /**重寫equals*/ public boolean equals(Object obj){ SingleResImpl res = (SingleResImpl)obj; return res.getName().equals(getName()) && res.getMoney()==getMoney(); }}
3.
多個物品(樹枝構件)
package com.eekq.structure.composite.security;import java.util.Iterator;import java.util.Vector;/* * 對多個物品的管理 * */public class MultiResImpl implements IRes { /**購物車*/ private Vector car = new Vector(); private static float totle = 0.0f; public void pay() { if(!car.isEmpty()){ System.out.println("名稱 價格\n"); shopping(); System.out.println("\n總價:" + totle + "元"); }else{ System.out.println("您好,你沒有購買任何物品,不用買單!"); } } public void shopping() { if (car != null || !car.isEmpty()) { Iterator it = car.iterator(); SingleResImpl res = null; Object temp = null;// 臨時對象 while (it.hasNext()) { temp = it.next(); if (temp instanceof MultiResImpl) { ((MultiResImpl) temp).shopping(); } else { res = (SingleResImpl) temp; synchronized (this) { totle += res.getMoney(); } System.out.println(res.getName() + " " + res.getMoney() + "元"); } } } } /**加入新的物品*/ public void addRes(IRes res) { car.add(res); } /**放回物品*/ public void removeRes(IRes res) { car.remove(res); } }
4.
收銀台買單
package com.eekq.structure.composite.security;public class Main { /** *@paramargs */ public static void main(String[] args) { /**買支雪糕*/ IRes singleRes = new SingleResImpl("雪糕", 1.5f); /**買單*/ singleRes.pay(); /**快過年了,我推了個購物車,多買點東西*/ IRes allRes = new MultiResImpl(); /**在一樓買的食物*/ IRes one = new MultiResImpl(); ((MultiResImpl) allRes).addRes(one);//把一樓的東西裝在購物車裡 /**因為是安全方式的組合模式,因此不夠透明,只能明確的向下轉型,然後再加入購物車了*/ ((MultiResImpl) one).addRes(new SingleResImpl("WangWang", 28.5f)); ((MultiResImpl) one).addRes(new SingleResImpl("糖果", 38.0f)); ((MultiResImpl) one).addRes(new SingleResImpl("可樂", 8.5f)); /**二樓去買的衣服和襪子*/ IRes two = new MultiResImpl(); ((MultiResImpl) allRes).addRes(two);// 把二樓的東西裝也裝在購物車裡 ((MultiResImpl) two).addRes(new SingleResImpl("衣服", 130.5f)); ((MultiResImpl) two).addRes(new SingleResImpl("襪子", 10f)); /**二樓再買了個手錶,我放在bao裡*/ IRes bao = new MultiResImpl(); ((MultiResImpl) two).addRes(bao);//把購物小封裝在二樓購物車裡 ((MultiResImpl) bao).addRes(new SingleResImpl("手錶", 100f)); /**回到一樓,又買了蘋果和梨*/ ((MultiResImpl) one).addRes(new SingleResImpl("蘋果", 10.0f)); ((MultiResImpl) one).addRes(new SingleResImpl("梨", 3.0f));/**在買單之前我把可樂退了,因為家裡還有的嘛*/ ((MultiResImpl) one).removeRes(new SingleResImpl("可樂", 8.5f)); /**在收銀台一次性對購物車所有物品買單*/ allRes.pay(); }}
5.
運行結果購買了一件物品[雪糕],價錢是[1.5]元名稱 價格 WangWang 28.5元糖果 38.0元蘋果 10.0元梨 3.0元衣服 130.5元襪子 10.0元手錶 100.0元 總價:320.0元 (二)、透明方式透明方式與安全方式的不同點在於抽象構件,透明方式使用的是統一介面。1.
抽象構件
package com.eekq.structure.composite.clarity; /* * 抽象構件,物品 * */public interface IRes { /**購物買單,示意性的商業方法*/ public void pay(); /**加入新的物品*/ public void addRes(IRes res); /**放回物品*/ public void removeRes(IRes res);}
2.
單一物品(樹葉構件)
package com.eekq.structure.composite.security; public class SingleResImpl implements IRes { /**物品名稱*/ private String name; /**價錢*/ private float money; public SingleResImpl(String name, float money) { this.name = name; this.money = money; } public void pay() { System.out.println("購買了一件物品["+getName()+"],價錢是[" + getMoney()+"]元"); } public float getMoney() { // TODO 自動產生方法存根 return this.money; } public String getName() { // TODO 自動產生方法存根 return this.name; } /**重寫equals*/ public boolean equals(Object obj){ SingleResImpl res = (SingleResImpl)obj; return res.getName().equals(getName()) && res.getMoney()==getMoney(); } }
3.
多個物品(樹枝構件)
同安全模式代碼一樣!4.
收銀台買單
package com.eekq.structure.composite.clarity;public class Main { /** *@paramargs */ public static void main(String[] args) { /**買支雪糕*/ IRes singleRes = new SingleResImpl("雪糕", 1.5f); /**買單*/ singleRes.pay(); /**快過年了,我推了個購物車,多買點東西*/ IRes allRes = new MultiResImpl(); /**在一樓買的食物*/ IRes one = new MultiResImpl(); allRes.addRes(one);// 把一樓的東西裝在購物車裡 /**因為是透明方式的組合模式,因此直接調用就是了*/ one.addRes(new SingleResImpl("WangWang", 28.5f)); one.addRes(new SingleResImpl("糖果", 38.0f)); one.addRes(new SingleResImpl("可樂", 8.5f)); /**二樓去買的衣服和襪子*/ IRes two = new MultiResImpl(); allRes.addRes(two);// 把二樓的東西裝也裝在購物車裡 two.addRes(new SingleResImpl("衣服", 130.5f)); two.addRes(new SingleResImpl("襪子", 10f)); /**二樓再買了個手錶,我放在bao裡*/ IRes bao = new MultiResImpl(); two.addRes(bao);// 把購物小封裝在二樓購物車裡 bao.addRes(new SingleResImpl("手錶", 100f)); /**回到一樓,又買了蘋果和梨*/ one.addRes(new SingleResImpl("蘋果", 10.0f)); one.addRes(new SingleResImpl("梨", 3.0f)); /**在買單之前我把可樂退了,因為家裡還有的嘛*/ one.removeRes(new SingleResImpl("可樂", 8.5f)); /**在收銀台一次性對購物車所有物品買單*/ allRes.pay(); }}
5.
運行結果
同安全模式一樣的結果!四.總結合成模式是對象的結構模式,以上示範合成模式。在以後的項目中,如果遇到對象組合的情況,即也符合樹結構的。可以考慮下此模式。此模式中講述了安全方式和透明方式。安全方式:抽象構件上只提供樹葉和樹枝公用的方法,沒提供樹枝專屬的管理等方法(add(),remove())。這樣的好處是安全,使用者不會在樹葉上使用add()等管理方法,缺點是不夠透明,使用者必須知識當前對象為樹葉還是樹枝(向下轉型)。透明方式:抽象構件上提供了滿足樹枝的所有方法(包括add(),remove()),這樣做的好處是,使用者可以任意執行對象的add()和remove()管理對象。缺點是如果使用者在樹葉上執行管理方式(add(),remove())時,在編譯期不會有錯,但在執行期會報錯,這樣不容易被發覺錯誤出在哪.
如果以上內容不明白,推薦部落格地址:http://lavasoft.blog.51cto.com/62575/90824/
下面的資料來源:Steven John Metsker 和william C. wake 著 的 java設計模式(第二版)第五章內容:僅供大家參考和學習!
著作權聲明:歡迎轉載,希望在你轉載的同時,添加原文地址,謝謝配合
《Java設計模式》之合成模式