設計模式 裝飾者模式 帶你重回傳奇世界

今天繼續設計模式之旅,給大家帶來裝飾者模式,國際慣例,先看定義。

裝飾者模式:若要擴展功能,裝飾者提供了比集成更有彈性的替代方案,動態地將責任附加到對象上。

先簡單描述下裝飾者模式發揮作用的地方,當我們設計好了一個類,我們需要給這個類添加一些輔助的功能,並且不希望改變這個類的代碼,這時候就是裝飾者模式大展雄威的時候了。這裏還體現了一個原則:類應該對擴展開放,對修改關閉。

下面進入正題,今天在那看電影,忽然想起年輕時在遊戲場上的血雨腥風啊,哈哈,下面以遊戲爲背景介紹裝飾者模式。玩過遊戲的兄弟應該都知道,遊戲裏面每個角色有武器、鞋子、護腕、戒指、還有各種紅寶石、藍寶石、黃寶石等等。

下面需求開始:設計遊戲的裝備系統,基本要求,要可以計算出每種裝備在鑲嵌了各種寶石後的攻擊力和描述:

具體需求:

1、武器(攻擊力20) 、戒指(攻擊力5)、護腕(攻擊力5)、鞋子(攻擊力5)

2、藍寶石(攻擊力5/顆)、黃寶石(攻擊力10/顆)、紅寶石(攻擊力15/顆)

3、每個裝備可以隨意鑲嵌3顆


好了,需求介紹完畢,當然了,不要吐槽我的設計,尼瑪鞋子哪來的攻擊力,關鍵時刻也是可以砸人的嘛。下面開始初步的設想,出於多年面向對象的經驗,我們可能會這麼設計:

如果你這麼設計了,我靠,就這麼點需求你寫了幾百個類,隨便添加兩個寶石,哈哈,指數增長聽過麼,準備加班吧。

可能你還會這麼設計:寫一個超類,然後裏面各種set寶石,然後在計算攻擊力的地方,使勁的If有哪幾種寶石,恭喜你,代碼量不是很大,但是隨便添加個武器,你得又多寫多少個IF呢。

上面敘述了一些可能性的設計,都不是很好,下面看看如何將裝飾者模式融入:

首先是裝備的超類

  1. package com.zhy.pattern.decorator;  
  2.   
  3. /** 
  4.  * 裝備的接口 
  5.  *  
  6.  * @author zhy 
  7.  *  
  8.  */  
  9. public interface IEquip  
  10. {  
  11.   
  12.     /** 
  13.      * 計算攻擊力 
  14.      *  
  15.      * @return 
  16.      */  
  17.     public int caculateAttack();  
  18.   
  19.     /** 
  20.      * 裝備的描述 
  21.      *  
  22.      * @return 
  23.      */  
  24.     public String description();  
  25. }  

然後分別是武器、戒指、護腕、鞋子

  1. package com.zhy.pattern.decorator;  
  2.   
  3. /** 
  4.  * 武器 
  5.  * 攻擊力20 
  6.  * @author zhy 
  7.  *  
  8.  */  
  9. public class ArmEquip implements IEquip  
  10. {  
  11.   
  12.     @Override  
  13.     public int caculateAttack()  
  14.     {  
  15.         return 20;  
  16.     }  
  17.   
  18.     @Override  
  19.     public String description()  
  20.     {  
  21.         return “屠龍刀”;  
  22.     }  
  23.   
  24. }  

  1. package com.zhy.pattern.decorator;  
  2.   
  3. /** 
  4.  * 戒指 
  5.  * 攻擊力 5 
  6.  * @author zhy 
  7.  * 
  8.  */  
  9. public class RingEquip implements IEquip  
  10. {  
  11.   
  12.     @Override  
  13.     public int caculateAttack()  
  14.     {  
  15.         return 5;  
  16.     }  
  17.   
  18.     @Override  
  19.     public String description()  
  20.     {  
  21.         return “聖戰戒指”;  
  22.     }  
  23.   
  24. }  

  1. package com.zhy.pattern.decorator;  
  2.   
  3. /** 
  4.  * 護腕 
  5.  * 攻擊力 5 
  6.  * @author zhy 
  7.  * 
  8.  */  
  9. public class WristEquip implements IEquip  
  10. {  
  11.   
  12.     @Override  
  13.     public int caculateAttack()  
  14.     {  
  15.         return 5;  
  16.     }  
  17.   
  18.     @Override  
  19.     public String description()  
  20.     {  
  21.         return “聖戰護腕”;  
  22.     }  
  23.   
  24. }  

  1. package com.zhy.pattern.decorator;  
  2.   
  3. /** 
  4.  * 鞋子 
  5.  * 攻擊力 5 
  6.  * @author zhy 
  7.  *  
  8.  */  
  9. public class ShoeEquip implements IEquip  
  10. {  
  11.   
  12.     @Override  
  13.     public int caculateAttack()  
  14.     {  
  15.         return 5;  
  16.     }  
  17.   
  18.     @Override  
  19.     public String description()  
  20.     {  
  21.         return “聖戰靴子”;  
  22.     }  
  23.   
  24. }  

接下來當然是裝飾品,寶石了,首先超類

  1. package com.zhy.pattern.decorator;  
  2.   
  3. /** 
  4.  * 裝飾品的接口 
  5.  * @author zhy 
  6.  * 
  7.  */  
  8. public interface IEquipDecorator extends IEquip  
  9. {  
  10.       
  11. }  

下來藍寶石、黃寶石、紅寶石

  1. package com.zhy.pattern.decorator;  
  2.   
  3. /** 
  4.  * 藍寶石裝飾品 
  5.  * 每顆攻擊力+5 
  6.  * @author zhy 
  7.  *  
  8.  */  
  9. public class BlueGemDecorator implements IEquipDecorator  
  10. {  
  11.     /** 
  12.      * 每個裝飾品維護一個裝備 
  13.      */  
  14.     private IEquip equip;  
  15.   
  16.     public BlueGemDecorator(IEquip equip)  
  17.     {  
  18.         this.equip = equip;  
  19.     }  
  20.   
  21.     @Override  
  22.     public int caculateAttack()  
  23.     {  
  24.         return 5 + equip.caculateAttack();  
  25.     }  
  26.   
  27.     @Override  
  28.     public String description()  
  29.     {  
  30.         return equip.description() + “+ 藍寶石”;  
  31.     }  
  32.   
  33. }  

  1. package com.zhy.pattern.decorator;  
  2.   
  3. /** 
  4.  * 黃寶石裝飾品 
  5.  * 每顆攻擊力+10 
  6.  * @author zhy 
  7.  *  
  8.  */  
  9. public class YellowGemDecorator implements IEquipDecorator  
  10. {  
  11.     /** 
  12.      * 每個裝飾品維護一個裝備 
  13.      */  
  14.     private IEquip equip;  
  15.   
  16.     public YellowGemDecorator(IEquip equip)  
  17.     {  
  18.         this.equip = equip;  
  19.     }  
  20.   
  21.     @Override  
  22.     public int caculateAttack()  
  23.     {  
  24.         return 10 + equip.caculateAttack();  
  25.     }  
  26.   
  27.     @Override  
  28.     public String description()  
  29.     {  
  30.         return equip.description() + “+ 黃寶石”;  
  31.     }  
  32.   
  33. }  

  1. package com.zhy.pattern.decorator;  
  2.   
  3. /** 
  4.  * 紅寶石裝飾品 每顆攻擊力+15 
  5.  *  
  6.  * @author zhy 
  7.  *  
  8.  */  
  9. public class RedGemDecorator implements IEquipDecorator  
  10. {  
  11.     /** 
  12.      * 每個裝飾品維護一個裝備 
  13.      */  
  14.     private IEquip equip;  
  15.   
  16.     public RedGemDecorator(IEquip equip)  
  17.     {  
  18.         this.equip = equip;  
  19.     }  
  20.   
  21.     @Override  
  22.     public int caculateAttack()  
  23.     {  
  24.         return 15 + equip.caculateAttack();  
  25.     }  
  26.   
  27.     @Override  
  28.     public String description()  
  29.     {  
  30.         return equip.description() + “+ 紅寶石”;  
  31.     }  
  32.   
  33. }  

好了,到此結束,我們已經實現了需求的功能了,是不是每個類都很清晰加簡單,下面看測試:

  1. package com.zhy.pattern.decorator;  
  2.   
  3. public class Test  
  4. {  
  5.     public static void main(String[] args)  
  6.     {  
  7.         // 一個鑲嵌2顆紅寶石,1顆藍寶石的靴子  
  8.         System.out.println(” 一個鑲嵌2顆紅寶石,1顆藍寶石的靴子”);  
  9.         IEquip equip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));  
  10.         System.out.println(”攻擊力  : ” + equip.caculateAttack());  
  11.         System.out.println(”描述 :” + equip.description());  
  12.         System.out.println(”——-“);  
  13.         // 一個鑲嵌1顆紅寶石,1顆藍寶石的武器  
  14.         System.out.println(” 一個鑲嵌1顆紅寶石,1顆藍寶石,1顆黃寶石的武器”);  
  15.         equip = new RedGemDecorator(new BlueGemDecorator(new YellowGemDecorator(new ArmEquip())));  
  16.         System.out.println(”攻擊力  : ” + equip.caculateAttack());  
  17.         System.out.println(”描述 :” + equip.description());  
  18.         System.out.println(”——-“);  
  19.     }  
  20. }  

輸出:

  1.  一個鑲嵌2顆紅寶石,1顆藍寶石的靴子  
  2. 攻擊力  : 40  
  3. 描述 :聖戰靴子+ 藍寶石+ 紅寶石+ 紅寶石  
  4. ——-  
  5.  一個鑲嵌1顆紅寶石,1顆藍寶石,1顆黃寶石的武器  
  6. 攻擊力  : 50  
  7. 描述 :屠龍刀+ 黃寶石+ 藍寶石+ 紅寶石  
  8. ——-  

贊不讚,要是需求隨便多幾個裝備,幾種寶石,我們隨隨便便就可以加上,然後開開心心下班。


好了,恭喜你,你又學會了一個設計模式,裝飾者模式。

現在根據例子對定義的理解,不用我多說吧。


Java的API中也有裝飾者模式的身影,如果你初學Java,一定記得Java裏面的各種流,很痛苦吧,但是當你明

白你們的設計之後就會感覺清晰很多。


把InputStream看作我們的IEquip,把FilterInputStream看作我們的IEquipDecorator,是不是和我們的設計幾乎一樣~


好了,就到這裏,編程也是很有樂趣的麼~是吧,各位看官留個言、給個讚唄~



源碼點擊下載

原文地址:http://blog.csdn.net/lmj623565791/article/details/24269409





發佈了4 篇原創文章 · 獲贊 11 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章