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

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

- package decorator.demo;
-
- /**
- * 其他用來(lái)添加蛋糕的東西
- * @author Nicholas
- *
- */
- public abstract class OtherDecorator extends Cake{
- Cake cake;
- /**
- * 引用一個(gè)Cake.
- * 讓被裝飾者進(jìn)入裝飾者之中。這里用的是構(gòu)造方法注入。
- * 這樣就可以調(diào)用Cake實(shí)例的方法了。
- * @param cake
- */
- public OtherDecorator(Cake cake){
- this.cake=cake;
- }
- /**
- * 讓裝飾器的子類都去實(shí)現(xiàn)getRemark方法。業(yè)務(wù)需要每個(gè)裝飾器都要有描述。
- */
- public abstract String getRemark();
- }
下面讓我們實(shí)現(xiàn)一個(gè)蛋糕吧。^_^。。
Java代碼

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

- package decorator.demo;
-
- /**
- * 給蛋糕添加的花
- * @author Nicholas
- *
- */
- public class FlowerDecorator extends OtherDecorator{
-
- /**
- * 構(gòu)造函數(shù)
- * 傳入一個(gè)cake實(shí)例,也就是前面所實(shí)現(xiàn)的Cake的子類,如奶酪蛋糕,巧克力蛋糕等等。
- * @param cake
- */
- public FlowerDecorator(Cake cake){
- super(cake);//調(diào)用父類的構(gòu)造方法,可以獲取Cake的實(shí)例了。就可以調(diào)用Cake實(shí)例的方法.
- super.remark="一朵玫瑰花";
- }
-
- /**
- * 實(shí)現(xiàn)了裝飾器抽象類的getImpression方法。
- */
- public String getImpression() {
- //這是重點(diǎn)。我們通過(guò)構(gòu)造方法傳入的cake實(shí)例。對(duì)cake進(jìn)行了裝飾,增加了新的功能。
- return cake.getImpression()+","+"看到一朵花真是happy";
- }
-
- public String getRemark() {
- return cake.getRemark()+"+"+super.remark;
- }
- }
到現(xiàn)在終于大功告成了。。這樣方便了很多,可以通過(guò)裝飾器生成很多種類的蛋糕。
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());
- //吃蛋糕的感受已經(jīng)發(fā)生了改變。
- System.out.println("impression "+nutsFlowerChocolateCake.getImpression());
- }
- }
這個(gè)模式的缺點(diǎn)也挺明顯的 ,看看如下圖片
為了擴(kuò)展cake的功能,加入了許多的裝飾類。。當(dāng)然用戶也可以繼承OtherDecorator來(lái)繼續(xù)擴(kuò)展。但是對(duì)API使用者是個(gè)困擾。。所以API要說(shuō)明哪些類是用來(lái)包裝的。。