《Java設計模式》之合成模式

合成模式
合成模式把部分和整體關係用樹結構表示,是屬於對象的結構模式。合成模式要對組合的對象進行管理,所以在一定位置給予對象的相關管理方法,如:add(),remove()等.合成模式中對象的管理有兩種方案。
1.安全方式:此方式只允許樹枝構件有對象的管理方法。
2.透明方式:此方式只允許樹枝和樹葉都有對象的管理方法,但樹葉對象中的管理方法無實際意義。
一.UML示意圖
二.組成部分
抽象構件:抽象組合對象的公共行爲接口
樹葉構件:樹葉對象,沒有下級子對象
樹枝構件:樹枝對象,樹枝對象可以包含一個或多個其他樹枝或樹葉對象
三.代碼例子:我以一個超市購物爲例
(一)、安全方式
1.抽象物品(抽象構件)
[java] view plain copy
  1. package com.eekq.structure.composite.security;  
  2. /* 
  3.  * 抽象構件,物品 
  4.  * */  
  5. public interface IRes {  
  6.     /**購物買單,示意性的商業方法*/  
  7.     public void pay();  
  8.  


2.單一物品(樹葉構件)
[java] view plain copy
  1. package com.eekq.structure.composite.security;  
  2. public class SingleResImpl implements IRes {  
  3.     /**物品名稱*/  
  4.     private String name;  
  5.     /**價錢*/  
  6.     private float money;  
  7.     public SingleResImpl(String name, float money) {  
  8.         this.name = name;  
  9.         this.money = money;  
  10.     }  
  11.     public void pay() {  
  12.         System.out.println("購買了一件物品["+getName()+"],價錢是[" + getMoney()+"]元");  
  13.     }  
  14.     public float getMoney() {  
  15.         // TODO 自動生成方法存根  
  16.         returnthis.money;  
  17.     }  
  18.     public String getName() {  
  19.         // TODO 自動生成方法存根  
  20.         return this.name;  
  21.     }    
  22.     /**重寫equals*/  
  23.     public boolean equals(Object obj){  
  24.         SingleResImpl res = (SingleResImpl)obj;      
  25.         return res.getName().equals(getName()) && res.getMoney()==getMoney();  
  26.     }  
  27. }  


3.多個物品(樹枝構件)
[java] view plain copy
  1. package com.eekq.structure.composite.security;  
  2. import java.util.Iterator;  
  3. import java.util.Vector;  
  4. /* 
  5.  * 對多個物品的管理 
  6.  * */  
  7. public class MultiResImpl implements IRes {  
  8.     /**購物車*/  
  9.     private Vector car = new Vector();  
  10.     private static float totle = 0.0f;  
  11.        
  12. public void pay() {  
  13.         if(!car.isEmpty()){  
  14.         System.out.println("名稱        價格\n");  
  15.         shopping();  
  16.         System.out.println("\n總價:" + totle + "元");  
  17.         }else{  
  18.             System.out.println("您好,你沒有購買任何物品,不用買單!");         
  19.         }  
  20.     }  
  21.     public void shopping() {        
  22.         if (car != null || !car.isEmpty()) {  
  23.             Iterator it = car.iterator();  
  24.             SingleResImpl res = null;  
  25.             Object temp = null;// 臨時對象  
  26.             while (it.hasNext()) {  
  27.                 temp = it.next();  
  28.                 if (temp instanceof MultiResImpl) {  
  29.                     ((MultiResImpl) temp).shopping();  
  30.                 } else {  
  31.                     res = (SingleResImpl) temp;  
  32.                     synchronized (this) {  
  33.                         totle += res.getMoney();  
  34.                     }  
  35.                     System.out.println(res.getName() + "            " + res.getMoney()  
  36.                             + "元");  
  37.                 }  
  38.             }  
  39.         }  
  40.     }  
  41.     /**加入新的物品*/  
  42.     public void addRes(IRes res) {  
  43.         car.add(res);  
  44.     }  
  45.    
  46.     /**放回物品*/  
  47.     public void removeRes(IRes res) {  
  48.         car.remove(res);  
  49.     }  
  50.    
  51. }  
  52.    


4.收銀臺買單
[java] view plain copy
  1. package com.eekq.structure.composite.security;  
  2. public class Main {  
  3.     /** 
  4.      *@paramargs 
  5.      */  
  6.     public static void main(String[] args) {  
  7.         /**買支雪糕*/  
  8.         IRes singleRes = new SingleResImpl("雪糕"1.5f);  
  9.         /**買單*/  
  10.         singleRes.pay();  
  11.    
  12.         /**快過年了,我推了個購物車,多買點東西*/  
  13.         IRes allRes = new MultiResImpl();                
  14.         /**在一樓買的食物*/  
  15.         IRes one = new MultiResImpl();  
  16.         ((MultiResImpl) allRes).addRes(one);//把一樓的東西裝在購物車裏  
  17.         /**因爲是安全方式的組合模式,因此不夠透明,只能明確的向下轉型,然後再加入購物車了*/  
  18.         ((MultiResImpl) one).addRes(new SingleResImpl("旺旺"28.5f));  
  19.         ((MultiResImpl) one).addRes(new SingleResImpl("糖果"38.0f));  
  20.         ((MultiResImpl) one).addRes(new SingleResImpl("可樂"8.5f));  
  21.    
  22.         /**二樓去買的衣服和襪子*/  
  23.         IRes two = new MultiResImpl();  
  24.         ((MultiResImpl) allRes).addRes(two);// 把二樓的東西裝也裝在購物車裏  
  25.         ((MultiResImpl) two).addRes(new SingleResImpl("衣服"130.5f));  
  26.         ((MultiResImpl) two).addRes(new SingleResImpl("襪子", 10f));         
  27.         /**二樓再買了個手錶,我放在bao裏*/  
  28.         IRes bao = new MultiResImpl();  
  29.         ((MultiResImpl) two).addRes(bao);//把購物小包裝在二樓購物車裏  
  30.         ((MultiResImpl) bao).addRes(new SingleResImpl("手錶", 100f));  
  31.          
  32.         /**回到一樓,又買了蘋果和梨*/  
  33.         ((MultiResImpl) one).addRes(new SingleResImpl("蘋果"10.0f));  
  34.         ((MultiResImpl) one).addRes(new SingleResImpl("梨"3.0f));  
  35. /**在買單之前我把可樂退了,因爲家裏還有的嘛*/  
  36.         ((MultiResImpl) one).removeRes(new SingleResImpl("可樂"8.5f));  
  37.         /**在收銀臺一次性對購物車所有物品買單*/  
  38.         allRes.pay();  
  39.     }  
  40. }  


 
5.運行結果
購買了一件物品[雪糕],價錢是[1.5]元
名稱        價格
 
旺旺        28.5元
糖果        38.0元
蘋果        10.0元
梨          3.0元
衣服        130.5元
襪子        10.0元
手錶        100.0元
 
總價:320.0元
 
(二)、透明方式
透明方式與安全方式的不同點在於抽象構件,透明方式使用的是統一接口。
1. 抽象構件
[java] view plain copy
  1. package com.eekq.structure.composite.clarity;  
  2.    
  3. /* 
  4.  * 抽象構件,物品 
  5.  * */  
  6. public interface IRes {  
  7.     /**購物買單,示意性的商業方法*/  
  8.     public void pay();  
  9.    
  10.     /**加入新的物品*/  
  11.     public void addRes(IRes res);  
  12.    
  13.     /**放回物品*/  
  14.     public void removeRes(IRes res);  
  15.  


2. 單一物品(樹葉構件)
[java] view plain copy
  1. package com.eekq.structure.composite.security;  
  2.    
  3. public class SingleResImpl implements IRes {  
  4.    
  5.     /**物品名稱*/  
  6.     private String name;  
  7.    
  8.     /**價錢*/  
  9.     private float money;  
  10.    
  11.     public SingleResImpl(String name, float money) {  
  12.         this.name = name;  
  13.         this.money = money;  
  14.     }  
  15.    
  16.     public void pay() {  
  17.         System.out.println("購買了一件物品["+getName()+"],價錢是[" + getMoney()+"]元");  
  18.     }  
  19.    
  20.     public float getMoney() {  
  21.         // TODO 自動生成方法存根  
  22.         return this.money;  
  23.     }  
  24.    
  25.     public String getName() {  
  26.         // TODO 自動生成方法存根  
  27.         return this.name;  
  28.     }  
  29.      
  30.     /**重寫equals*/  
  31.     public boolean equals(Object obj){  
  32.         SingleResImpl res = (SingleResImpl)obj;      
  33.         return res.getName().equals(getName()) && res.getMoney()==getMoney();  
  34.     }  
  35.    
  36.  


3.多個物品(樹枝構件)
同安全模式代碼一樣!
4.收銀臺買單
 
[java] view plain copy
  1. package com.eekq.structure.composite.clarity;  
  2. public class Main {  
  3.     /** 
  4.      *@paramargs 
  5.      */  
  6.     public static void main(String[] args) {  
  7.         /**買支雪糕*/  
  8.         IRes singleRes = new SingleResImpl("雪糕"1.5f);  
  9.         /**買單*/  
  10.         singleRes.pay();  
  11.         /**快過年了,我推了個購物車,多買點東西*/  
  12.         IRes allRes = new MultiResImpl();  
  13.    
  14.         /**在一樓買的食物*/  
  15.         IRes one = new MultiResImpl();  
  16.         allRes.addRes(one);// 把一樓的東西裝在購物車裏  
  17.         /**因爲是透明方式的組合模式,因此直接調用就是了*/  
  18.         one.addRes(new SingleResImpl("旺旺"28.5f));  
  19.         one.addRes(new SingleResImpl("糖果"38.0f));  
  20.         one.addRes(new SingleResImpl("可樂"8.5f));  
  21.    
  22.         /**二樓去買的衣服和襪子*/  
  23.         IRes two = new MultiResImpl();  
  24.         allRes.addRes(two);// 把二樓的東西裝也裝在購物車裏  
  25.         two.addRes(new SingleResImpl("衣服"130.5f));  
  26.         two.addRes(new SingleResImpl("襪子", 10f));  
  27.         /**二樓再買了個手錶,我放在bao裏*/  
  28.         IRes bao = new MultiResImpl();  
  29.         two.addRes(bao);// 把購物小包裝在二樓購物車裏  
  30.         bao.addRes(new SingleResImpl("手錶", 100f));  
  31.         /**回到一樓,又買了蘋果和梨*/  
  32.         one.addRes(new SingleResImpl("蘋果"10.0f));  
  33.         one.addRes(new SingleResImpl("梨"3.0f));  
  34.         /**在買單之前我把可樂退了,因爲家裏還有的嘛*/  
  35.         one.removeRes(new SingleResImpl("可樂"8.5f));  
  36.         /**在收銀臺一次性對購物車所有物品買單*/  
  37.         allRes.pay();  
  38.     }  
  39.  


5.運行結果
同安全模式一樣的結果!
四.總結
合成模式是對象的結構模式,以上演示合成模式。在以後的項目中,如果遇到對象組合的情況,即也符合樹結構的。可以考慮下此模式。此模式中講述了安全方式和透明方式。
安全方式:抽象構件上只提供樹葉和樹枝公共的方法,沒提供樹枝獨有的管理等方法(add(),remove())。這樣的好處是安全,用戶不會在樹葉上使用add()等管理方法,缺點是不夠透明,用戶必須知識當前對象爲樹葉還是樹枝(向下轉型)。
透明方式:抽象構件上提供了滿足樹枝的所有方法(包括add(),remove()),這樣做的好處是,用戶可以任意執行對象的add()和remove()管理對象。缺點是如果用戶在樹葉上執行管理方式(add(),remove())時,在編譯期不會有錯,但在執行期會報錯,這樣不容易被發覺錯誤出在哪.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章