MM們要過生日了 ,怎么也得表示下吧。最起碼先送個蛋糕。蛋糕多種多樣了。巧克力,冰淇淋,奶油等等。這都是基本的了 ,再加點額外的裝飾,如蛋糕里放點花。放賀卡。放點干果吃著更香等等。看看我是如何設計的。
我想既然是蛋糕,那我就把蛋糕作為一個抽象類,剩下的蛋糕子類型來繼承它,每個子類都有吃該蛋糕的感覺 ^_^,看起來真的不錯。蛋糕的子類分別是奶酪蛋糕,巧克力蛋糕,冰淇淋蛋糕,插花的冰淇淋蛋糕,放賀卡的冰淇淋蛋糕。某個MM的生日蛋糕喜歡帶花的冰淇 淋蛋糕。還好我早有準備。但是有幾次失策了。。她們要的蛋糕我這都沒有。比如帶鮮花的巧克力蛋糕。帶果仁的牛奶蛋糕。帶鮮花帶果仁的蛋糕。。。。那我還要 繼續添加蛋糕的子類。。問題出現了。這樣會造成大量的蛋糕子類 。真是噩夢啊。
那么我要好好思考這個問題了。發現了剛才的設計確實有問題。。發現了真正的要關注的主體是蛋糕。。而賀卡,花,果仁等等只不過是裝飾 的作用。
思路來了。蛋糕作為主體,其他的東西都加到蛋糕上。MM要啥我就加啥唄。呵呵。
到現在我們要明確的是:
- 蛋糕是主體。
- 花,賀卡,果仁等等是裝飾者。
- 可以用裝飾者包裝蛋糕。
來看看什么是裝飾器模式吧:
動態的將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
- Component:抽象出的主體對象。
- ConcreteComponent:是要動態擴展的對象,它繼承自Component.
- Decorator:是裝飾器的接口。(這里的接口并不是指java的interface)。
- ConcreteDecoratorA:實現Decorator的類,包含了一個Component引用,這樣就可以擴展Component的方法了。
說完理論了。可能還一頭霧水吧。。。還是接著蛋糕的例子繼續說。先看圖吧。
基本符合了上面所提到的裝飾者模式的框架結構了。再看看代碼:
Cake
Java代碼

- package decorator.demo;
-
- /**
- * 蛋糕基類
- * @author Nicholas
- *
- */
- public abstract class Cake {
- String remark = "蛋糕";
- public String getRemark() {
- return remark;
- }
- public abstract String getImpression();//用來描述吃蛋糕的感覺。。。。
- }
Cake是個抽象類,它已經實現了getRemark的方法。但沒有實現getImpression.這個方法必須被子類實現。
再看看裝飾器的抽象類
OtherDecorator
Java代碼

- 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();
- }
下面讓我們實現一個蛋糕吧。^_^。。
Java代碼

- package decorator.demo;
- /**
- * 乳酪蛋糕
- * @author Nicholas
- *
- */
- public class CheeseCake extends Cake{
- /**
- * 乳酪蛋糕的構造方法
- */
- public CheeseCake(){
- super.remark="乳酪蛋糕";//修改乳酪蛋糕的描述。
- }
-
- /**
- * 實現了Cake抽象類的getImpression
- * 吃乳酪蛋糕的感覺。。
- */
- public String getImpression() {
- return "香甜感受";
- }
-
- }
其他實現Cake的類就不列出了,道理是一樣的。
下面我們要開始實現具體的裝飾器了。
Java代碼

- 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;
- }
- }
到現在終于大功告成了。。這樣方便了很多,可以通過裝飾器生成很多種類的蛋糕。
Java代碼

- 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要說明哪些類是用來包裝的。。