一、一個問題。
??或說國哥當年在創(chuàng)業(yè)開店---賣豆?jié){!因豆?jié){純。分店幾乎開遍全縣所有村,由于發(fā)展是在太快了,所以急需一套由計算機管理的自動化記賬系統(tǒng)。

繼承帶來的問題

二、裝飾者模式,看看它能為我們帶來什么驚喜吧!
??1、意圖
??動態(tài)的給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更為靈活。該模式以對客戶透明的方式擴展對象的功能。
??2、適用環(huán)境
??在不影響其他對象的情況下,以動態(tài)、透明的方式給單個對象添加職責。
??當不能采用子類的方式進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類。使得子類的數(shù)目呈現(xiàn)爆炸式增長。另外一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。
??3、類圖
??Component(被裝飾對象基類)
??定義對象的接口,可以給這些對象動態(tài)增加職責;
??concreateComponent(具體被裝飾的對象)
??定義具體的對象,Decorator可以給它增加額外的職責
??Decorator(裝飾者抽象類)
??維護指向Component實例的引用,定義與Component一致的接口;
??ConcreteDecorator(具體裝飾者)
??具體的裝飾對象,給內部持有的具體被裝飾對象增加具體的職責。

三、實例
1、涉及角色
抽象組件:定義一個抽象接口,來規(guī)范準備附加功能的類。
具體對象:將要被附加功能的類,實現(xiàn)抽象構建角色接口。
抽象裝飾者:持有對具體構件角色的引用并定義與抽象構建角色一致的接口。
具體裝飾:實現(xiàn)抽象裝飾者角色,負責為具體構件添加額外功能。
2、代碼實現(xiàn)
| 類 | 描述 |
|---|---|
| Drink.java | 被裝飾者對象的接口 |
| SoyaBeanMilk.java | 具體的被裝飾者對象 |
| EggDecorator.java | 具體裝飾者對象 |
| SugarDecorator.java | 具體裝飾者對象 |
| BlankBeanDecorator.java | 具體裝飾者對象 |
| Decorator.java | 裝飾者基類 |
| Test.java | 測試 |
項目目錄

Drink.java
package com.antiai.decorator;
public interface Drink {
float cost(); // 計算價格
String description(); // 描述
}
SoyaBean.java
package com.antiai.decorator;
/*
* 具體的被裝飾者類
* 豆?jié){
* */
public class SoyaBeanMilk implements Drink {
@Override
public float cost() {
return 10f;
}
@Override
public String description() {
return "純豆?jié){";
}
}
Decorator.java
package com.antiai.decorator;
/*
* 裝飾者基類
* */
public class Decorator implements Drink {
private Drink drink; // 要裝飾的對象
public Decorator(Drink drink){
this.drink = drink;
}
@Override
public float cost() {
return drink.cost();
}
@Override
public String description() {
return drink.description();
}
}
SugarDecorator
package com.antiai.decorator;
public class SugarDecorator extends Decorator {
public SugarDecorator(Drink drink) {
super(drink);
}
@Override
public float cost() {
return super.cost()+1.0f;
}
@Override
public String description() {
return super.description()+"+糖";
}
}
BlankBeanDecorator
package com.antiai.decorator;
public class BlankBeanDecorator extends Decorator {
public BlankBeanDecorator(Drink drink) {
super(drink);
}
@Override
public float cost() {
return super.cost()+2.0f;
}
@Override
public String description() {
return super.description()+"+黑豆";
}
}
EggDecorator
package com.antiai.decorator;
public class EggDecorator extends Decorator {
public EggDecorator(Drink drink) {
super(drink);
}
@Override
public float cost() {
return super.cost()+3.0f;
}
@Override
public String description() {
return super.description()+"+雞蛋";
}
}
Test.java
package com.antiai.decorator;
public class Test {
public static void main(String[] args) {
Drink drink = new SoyaBeanMilk();
SugarDecorator sugar = new SugarDecorator(drink);
EggDecorator egg = new EggDecorator(sugar);
BlankBeanDecorator blankBean = new BlankBeanDecorator(egg);
System.out.println("你點的豆?jié){是:"+ blankBean.description());
System.out.println("一共花了:"+blankBean.cost());
}
}
四、裝飾者模式小結
oo原則:動態(tài)地將責任附加到對象上。想要擴展功能,裝飾者提供有別于繼承的另一種選擇。
要點:
1、繼承屬于擴展形式之一,但不見得是達到彈性設計的最佳方案。
2、在我們的設計中,應該允許行為可以被拓展,而無需修改現(xiàn)有的代碼。
3、組合和委托可以用于在運行時動態(tài)地加上新的行為。
4、除了繼承,裝飾者模式也可以讓我們擴展行為。
5、裝飾者模式意味著一群裝飾者類,這些類用于包裝具體組件。
6、裝飾者類反映出被裝飾的組件類型(實際上,他們具有相同的類型,都經過接口或繼承實現(xiàn))。
7、裝飾者可以在被裝飾者的行為前面/后面加上自己的行為。甚至將裝飾者的整個行為取代掉。而達到特定的目的。
8、你可以有無數(shù)個裝飾者包裝一個對象。
9、裝飾者一般對組建的客戶是透明的,除非客戶程序依賴于組件的具體類型。