MM們要過生日了 ,怎么也得表示下吧。最起碼先送個蛋糕。蛋糕多種多樣了。巧克力,冰淇淋,奶油等等。這都是基本的了 ,再加點額外的裝飾,如蛋糕里放點花。放賀卡。放點干果吃著更香等等。看看我是如何設計的。
????? 我想既然是蛋糕,那我就把蛋糕作為一個抽象類,剩下的蛋糕子類型來繼承它,每個子類都有吃該蛋糕的感覺 ^_^,看起來真的不錯。蛋糕的子類分別是奶酪蛋糕,巧克力蛋糕,冰淇淋蛋糕,插花的冰淇淋蛋糕,放賀卡的冰淇淋蛋糕。某個MM的生日蛋糕喜歡帶花的冰淇淋蛋糕。還好我早有準備。但是有幾次失策了。。她們要的蛋糕我這都沒有。比如帶鮮花的巧克力蛋糕。帶果仁的牛奶蛋糕。帶鮮花帶果仁的蛋糕。。。。那我還要繼續添加蛋糕的子類。。問題出現了。
這樣會造成大量的蛋糕子類
。真是噩夢啊。
?
那么我要好好思考這個問題了。發現了剛才的設計確實有問題。。發現了真正的要關注的主體是蛋糕。。而賀卡,花,果仁等等只不過是 裝飾 的作用。
?
思路來了。蛋糕作為主體,其他的東西都加到蛋糕上。MM要啥我就加啥唄。呵呵。
到現在我們要明確的是:
- 蛋糕是主體。
- 花,賀卡,果仁等等是裝飾者。
- 可以用裝飾者包裝蛋糕。
來看看什么是裝飾器模式吧:
動態的將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
?
- Component:抽象出的主體對象。
- ConcreteComponent:是要動態擴展的對象,它繼承自Component.
- Decorator:是裝飾器的接口。(這里的接口并不是指java的interface)。
- ConcreteDecoratorA:實現Decorator的類,包含了一個Component引用,這樣就可以擴展Component的方法了。
說完理論了。可能還一頭霧水吧。。。還是接著蛋糕的例子繼續說。先看圖吧。
基本符合了上面所提到的裝飾者模式的框架結構了。再看看代碼:
Cake
- package ?decorator.demo; ??
- ??
- /** ?
- ?*?蛋糕基類 ?
- ?*?@author?Nicholas ?
- ?* ?
- ?*/ ??
- public ? abstract ? class ?Cake?{ ??
- ????String?remark?=? "蛋糕" ; ??
- ???? public ?String?getRemark()?{ ??
- ???????? return ?remark; ??
- ????} ??
- ???? public ? abstract ?String?getImpression(); //用來描述吃蛋糕的感覺。。。。 ??
- }??
package decorator.demo; /** * 蛋糕基類 * @author Nicholas * */ public abstract class Cake { String remark = "蛋糕"; public String getRemark() { return remark; } public abstract String getImpression();//用來描述吃蛋糕的感覺。。。。 }
?Cake是個抽象類,它已經實現了getRemark的方法。但沒有實現getImpression.這個方法必須被子類實現。
?
再看看裝飾器的抽象類
OtherDecorator
- package ?decorator.demo; ??
- ??
- /** ?
- ?*?其他用來添加蛋糕的東西 ?
- ?*?@author?Nicholas ?
- ?* ?
- ?*/ ??
- public ? abstract ? class ?OtherDecorator? extends ?Cake{ ??
- ????Cake?cake; ??
- ???? /** ?
- ?????*?引用一個Cake. ?
- ?????*?讓被裝飾者進入裝飾者之中。這里用的是構造方法注入。 ?
- ?????*?這樣就可以調用Cake實例的方法了。 ?
- ?????*?@param?cake ?
- ?????*/ ??
- ???? public ?OtherDecorator(Cake?cake){ ??
- ???????? this .cake=cake; ??
- ????} ??
- ???? /** ?
- ?????*?讓裝飾器的子類都去實現getRemark方法。業務需要每個裝飾器都要有描述。 ?
- ?????*/ ??
- ???? public ? abstract ?String?getRemark(); ??
- }??
package decorator.demo; /** * 其他用來添加蛋糕的東西 * @author Nicholas * */ public abstract class OtherDecorator extends Cake{ Cake cake; /** * 引用一個Cake. * 讓被裝飾者進入裝飾者之中。這里用的是構造方法注入。 * 這樣就可以調用Cake實例的方法了。 * @param cake */ public OtherDecorator(Cake cake){ this.cake=cake; } /** * 讓裝飾器的子類都去實現getRemark方法。業務需要每個裝飾器都要有描述。 */ public abstract String getRemark(); }
?
下面讓我們實現一個蛋糕吧。^_^。。
- package ?decorator.demo; ??
- /** ?
- ?*?乳酪蛋糕 ?
- ?*?@author?Nicholas ?
- ?* ?
- ?*/ ??
- public ? class ?CheeseCake? extends ?Cake{ ??
- ???? /** ?
- ?????*?乳酪蛋糕的構造方法 ?
- ?????*/ ??
- ???? public ?CheeseCake(){ ??
- ???????? super .remark= "乳酪蛋糕" ; //修改乳酪蛋糕的描述。 ??
- ????} ??
- ??
- ???? /** ?
- ?????*?實現了Cake抽象類的getImpression ?
- ?????*?吃乳酪蛋糕的感覺。。 ?
- ?????*/ ??
- ???? public ?String?getImpression()?{ ??
- ???????? return ? "香甜感受" ; ??
- ????} ??
- ??
- }??
package decorator.demo; /** * 乳酪蛋糕 * @author Nicholas * */ public class CheeseCake extends Cake{ /** * 乳酪蛋糕的構造方法 */ public CheeseCake(){ super.remark="乳酪蛋糕";//修改乳酪蛋糕的描述。 } /** * 實現了Cake抽象類的getImpression * 吃乳酪蛋糕的感覺。。 */ public String getImpression() { return "香甜感受"; } }
?
其他實現Cake的類就不列出了,道理是一樣的。
下面我們要開始實現具體的裝飾器了。
- package ?decorator.demo; ??
- ??
- /** ?
- ?*?給蛋糕添加的花 ?
- ?*?@author?Nicholas ?
- ?* ?
- ?*/ ??
- public ? class ?FlowerDecorator? extends ?OtherDecorator{ ??
- ???? ??
- ???? /** ?
- ?????*?構造函數 ?
- ?????*?傳入一個cake實例,也就是前面所實現的Cake的子類,如奶酪蛋糕,巧克力蛋糕等等。 ?
- ?????*?@param?cake ?
- ?????*/ ??
- ???? public ?FlowerDecorator(Cake?cake){ ??
- ???????? super (cake); //調用父類的構造方法,可以獲取Cake的實例了。就可以調用Cake實例的方法. ??
- ???????? super .remark= "一朵玫瑰花" ; ??
- ????} ??
- ???? ??
- ???? /** ?
- ?????*?實現了裝飾器抽象類的getImpression方法。 ?
- ?????*/ ??
- ???? public ?String?getImpression()?{ ??
- ???????? //這是重點。我們通過構造方法傳入的cake實例。對cake進行了裝飾,增加了新的功能。 ??
- ???????? return ?cake.getImpression()+ "," + "看到一朵花真是happy" ; ??
- ????} ??
- ??
- ???? public ?String?getRemark()?{ ??
- ???????? return ?cake.getRemark()+ "+" + super .remark; ??
- ????} ??
- }??
package decorator.demo; /** * 給蛋糕添加的花 * @author Nicholas * */ public class FlowerDecorator extends OtherDecorator{ /** * 構造函數 * 傳入一個cake實例,也就是前面所實現的Cake的子類,如奶酪蛋糕,巧克力蛋糕等等。 * @param cake */ public FlowerDecorator(Cake cake){ super(cake);//調用父類的構造方法,可以獲取Cake的實例了。就可以調用Cake實例的方法. super.remark="一朵玫瑰花"; } /** * 實現了裝飾器抽象類的getImpression方法。 */ public String getImpression() { //這是重點。我們通過構造方法傳入的cake實例。對cake進行了裝飾,增加了新的功能。 return cake.getImpression()+","+"看到一朵花真是happy"; } public String getRemark() { return cake.getRemark()+"+"+super.remark; } }
?到現在終于大功告成了。。這樣方便了很多,可以通過裝飾器生成很多種類的蛋糕。
- package ?decorator.demo; ??
- ??
- public ? class ?MyGirlB?{ ??
- ???? public ? static ? void ?main(String[]?args){ ??
- ???????? //用果仁,花包裝巧克力蛋糕。 ??
- ????????Cake?nutsFlowerChocolateCake?=? new ?NutsDecorator( new ?FlowerDecorator( new ?ChocolateCake())); ??
- ????????System.out.println( "remark?" +nutsFlowerChocolateCake.getRemark()); ??
- ???????? //吃蛋糕的感受已經發生了改變。 ??
- ????????System.out.println( "impression?" +nutsFlowerChocolateCake.getImpression()); ??
- ????} ??
- }??
package decorator.demo; public class MyGirlB { public static void main(String[] args){ //用果仁,花包裝巧克力蛋糕。 Cake nutsFlowerChocolateCake = new NutsDecorator(new FlowerDecorator(new ChocolateCake())); System.out.println("remark "+nutsFlowerChocolateCake.getRemark()); //吃蛋糕的感受已經發生了改變。 System.out.println("impression "+nutsFlowerChocolateCake.getImpression()); } }
?
這個模式的缺點也挺明顯的 ,看看如下圖片
?
?
為了擴展cake的功能,加入了許多的裝飾類。。當然用戶也可以繼承OtherDecorator來繼續擴展。但是對API使用者是個困擾。。所以API要說明哪些類是用來包裝的。。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
