今天繼續(xù)設(shè)計(jì)模式之旅,給大家?guī)?lái)裝飾者模式,國(guó)際慣例,先看定義。
裝飾者模式:若要擴(kuò)展功能,裝飾者提供了比集成更有彈性的替代方案,動(dòng)態(tài)地將責(zé)任附加到對(duì)象上。
先簡(jiǎn)單描述下裝飾者模式發(fā)揮作用的地方,當(dāng)我們?cè)O(shè)計(jì)好了一個(gè)類,我們需要給這個(gè)類添加一些輔助的功能,并且不希望改變這個(gè)類的代碼,這時(shí)候就是裝飾者模式大展雄威的時(shí)候了。這里還體現(xiàn)了一個(gè)原則:類應(yīng)該對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。
下面進(jìn)入正題,今天在那看電影,忽然想起年輕時(shí)在游戲場(chǎng)上的血雨腥風(fēng)啊,哈哈,下面以游戲?yàn)楸尘敖榻B裝飾者模式。玩過(guò)游戲的兄弟應(yīng)該都知道,游戲里面每個(gè)角色有武器、鞋子、護(hù)腕、戒指、還有各種紅寶石、藍(lán)寶石、黃寶石等等。
下面需求開始:設(shè)計(jì)游戲的裝備系統(tǒng),基本要求,要可以計(jì)算出每種裝備在鑲嵌了各種寶石后的攻擊力和描述:
具體需求:
1、武器(攻擊力20) 、戒指(攻擊力5)、護(hù)腕(攻擊力5)、鞋子(攻擊力5)
2、藍(lán)寶石(攻擊力5/顆)、黃寶石(攻擊力10/顆)、紅寶石(攻擊力15/顆)
3、每個(gè)裝備可以隨意鑲嵌3顆
好了,需求介紹完畢,當(dāng)然了,不要吐槽我的設(shè)計(jì),尼瑪鞋子哪來(lái)的攻擊力,關(guān)鍵時(shí)刻也是可以砸人的嘛。下面開始初步的設(shè)想,出于多年面向?qū)ο蟮慕?jīng)驗(yàn),我們可能會(huì)這么設(shè)計(jì):

如果你這么設(shè)計(jì)了,我靠,就這么點(diǎn)需求你寫了幾百個(gè)類,隨便添加兩個(gè)寶石,哈哈,指數(shù)增長(zhǎng)聽(tīng)過(guò)么,準(zhǔn)備加班吧。
可能你還會(huì)這么設(shè)計(jì):寫一個(gè)超類,然后里面各種set寶石,然后在計(jì)算攻擊力的地方,使勁的If有哪幾種寶石,恭喜你,代碼量不是很大,但是隨便添加個(gè)武器,你得又多寫多少個(gè)IF呢。
上面敘述了一些可能性的設(shè)計(jì),都不是很好,下面看看如何將裝飾者模式融入:
首先是裝備的超類
package com.zhy.pattern.decorator;    /**  * 裝備的接口  *   * @author zhy  *   */  public interface IEquip  {        /**      * 計(jì)算攻擊力      *       * @return      */      public int caculateAttack();        /**      * 裝備的描述      *       * @return      */      public String description();  }  然后分別是武器、戒指、護(hù)腕、鞋子package com.zhy.pattern.decorator;    /**  * 武器  * 攻擊力20  * @author zhy  *   */  public class ArmEquip implements IEquip  {        @Override      public int caculateAttack()      {          return 20;      }        @Override      public String description()      {          return "屠龍刀";      }    }  package com.zhy.pattern.decorator;    /**  * 戒指  * 攻擊力 5  * @author zhy  *  */  public class RingEquip implements IEquip  {        @Override      public int caculateAttack()      {          return 5;      }        @Override      public String description()      {          return "圣戰(zhàn)戒指";      }    }  package com.zhy.pattern.decorator;    /**  * 護(hù)腕  * 攻擊力 5  * @author zhy  *  */  public class WristEquip implements IEquip  {        @Override      public int caculateAttack()      {          return 5;      }        @Override      public String description()      {          return "圣戰(zhàn)護(hù)腕";      }    }  package com.zhy.pattern.decorator;    /**  * 鞋子  * 攻擊力 5  * @author zhy  *   */  public class ShoeEquip implements IEquip  {        @Override      public int caculateAttack()      {          return 5;      }        @Override      public String description()      {          return "圣戰(zhàn)靴子";      }    }  接下來(lái)當(dāng)然是裝飾品,寶石了,首先超類package com.zhy.pattern.decorator;    /**  * 裝飾品的接口  * @author zhy  *  */  public interface IEquipDecorator extends IEquip  {        }  下來(lái)藍(lán)寶石、黃寶石、紅寶石package com.zhy.pattern.decorator;    /**  * 藍(lán)寶石裝飾品  * 每顆攻擊力+5  * @author zhy  *   */  public class BlueGemDecorator implements IEquipDecorator  {      /**      * 每個(gè)裝飾品維護(hù)一個(gè)裝備      */      PRivate IEquip equip;        public BlueGemDecorator(IEquip equip)      {          this.equip = equip;      }        @Override      public int caculateAttack()      {          return 5 + equip.caculateAttack();      }        @Override      public String description()      {          return equip.description() + "+ 藍(lán)寶石";      }    }  package com.zhy.pattern.decorator;    /**  * 黃寶石裝飾品  * 每顆攻擊力+10  * @author zhy  *   */  public class YellowGemDecorator implements IEquipDecorator  {      /**      * 每個(gè)裝飾品維護(hù)一個(gè)裝備      */      private IEquip equip;        public YellowGemDecorator(IEquip equip)      {          this.equip = equip;      }        @Override      public int caculateAttack()      {          return 10 + equip.caculateAttack();      }        @Override      public String description()      {          return equip.description() + "+ 黃寶石";      }    }  package com.zhy.pattern.decorator;    /**  * 紅寶石裝飾品 每顆攻擊力+15  *   * @author zhy  *   */  public class RedGemDecorator implements IEquipDecorator  {      /**      * 每個(gè)裝飾品維護(hù)一個(gè)裝備      */      private IEquip equip;        public RedGemDecorator(IEquip equip)      {          this.equip = equip;      }        @Override      public int caculateAttack()      {          return 15 + equip.caculateAttack();      }        @Override      public String description()      {          return equip.description() + "+ 紅寶石";      }    }  好了,到此結(jié)束,我們已經(jīng)實(shí)現(xiàn)了需求的功能了,是不是每個(gè)類都很清晰加簡(jiǎn)單,下面看測(cè)試:package com.zhy.pattern.decorator;    public class Test  {      public static void main(String[] args)      {          // 一個(gè)鑲嵌2顆紅寶石,1顆藍(lán)寶石的靴子          System.out.println(" 一個(gè)鑲嵌2顆紅寶石,1顆藍(lán)寶石的靴子");          IEquip equip = new RedGemDecorator(new RedGemDecorator(new BlueGemDecorator(new ShoeEquip())));          System.out.println("攻擊力  : " + equip.caculateAttack());          System.out.println("描述 :" + equip.description());          System.out.println("-------");          // 一個(gè)鑲嵌1顆紅寶石,1顆藍(lán)寶石的武器          System.out.println(" 一個(gè)鑲嵌1顆紅寶石,1顆藍(lán)寶石,1顆黃寶石的武器");          equip = new RedGemDecorator(new BlueGemDecorator(new YellowGemDecorator(new ArmEquip())));          System.out.println("攻擊力  : " + equip.caculateAttack());          System.out.println("描述 :" + equip.description());          System.out.println("-------");      }  }  輸出:一個(gè)鑲嵌2顆紅寶石,1顆藍(lán)寶石的靴子  攻擊力  : 40  描述 :圣戰(zhàn)靴子+ 藍(lán)寶石+ 紅寶石+ 紅寶石  -------   一個(gè)鑲嵌1顆紅寶石,1顆藍(lán)寶石,1顆黃寶石的武器  攻擊力  : 50  描述 :屠龍刀+ 黃寶石+ 藍(lán)寶石+ 紅寶石  -------  贊不贊,要是需求隨便多幾個(gè)裝備,幾種寶石,我們隨隨便便就可以加上,然后開開心心下班。好了,恭喜你,你又學(xué)會(huì)了一個(gè)設(shè)計(jì)模式,裝飾者模式。
現(xiàn)在根據(jù)例子對(duì)定義的理解,不用我多說(shuō)吧。
java的API中也有裝飾者模式的身影,如果你初學(xué)Java,一定記得Java里面的各種流,很痛苦吧,但是當(dāng)你明
白你們的設(shè)計(jì)之后就會(huì)感覺(jué)清晰很多

把InputStream看作我們的IEquip,把FilterInputStream看作我們的IEquipDecorator,是不是和我們的設(shè)計(jì)幾乎一樣~
好了,就到這里,編程也是很有樂(lè)趣的么~是吧,各位看官留個(gè)言、給個(gè)贊唄~
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注