裝飾者模式是JDK中另一個使用較多的設計模式,上一個是觀察者模式(在Swing中大量使用),業內好的API設計無一離不開常見的設計模式,通常我們所說要閱讀源碼,也是爲了學習大牛們的設計思路。————題記
設計模式
觀察者模式:定義了對象之間一對多的依賴,這樣一來,當一個對象改變狀態時,它的所有依賴者都會受到通知並自動更新。
裝飾者模式:動態地將責任附加到對象上。若要擴展功能,裝飾者提供比繼承者更有彈性的替代方案。
設計原則
(1)封裝變化。
(2)多用組合,少用繼承。
(3)針對接口編程,而不是針對實現編程。
(4)爲了交互對象之間的松耦合設計努力。
對象之間的像話依賴降到了最低,有助於簡歷有彈性的OO系統,能夠應對變化。
(5)類應該對擴展開發,對修改關閉。
目標是允許類容易擴展,在不修改現有代碼的情況下,就可以搭配出新的行爲。
要點
觀察者模式定義了對象之間一對多的關係。
使用觀察者模式時,可以從被觀察者出推或拉數據。
觀察者模式中,會改變的是主題的狀態,以及觀察者的數量和類型。用這個模式,你可以改變依賴於主題狀態的對象,卻不必改變主題。
繼承屬於擴展形式之一,但不見得是達到彈性設計的最佳方式。
組合和委託可用於運行時動態加上新的行爲。
裝飾者可以在被裝飾者的行爲前面與或後面加上自己的行爲,甚至取代,達到特有的目的。
裝飾者會導致設計中出現許多小對象,如果過度使用,會讓小程序變得複雜。
Java內置的觀察者模式:Obverser接口與Obversable類。
缺點:
(1)Obversable是一個類,必須設計一個類繼承他。如果想同時具有Obversable類和另一個超類的行爲,就會陷入兩難,因爲Java不支持多重繼承。Obversable沒有接口,無法建立自己的實現。
(2)Obversable將setChange()方法保護起來了。這樣一來,除非繼承,否則無法創建Obversable實例並組合到自己的對象中來。
真實世界的裝飾者
java.io包內的類太多了,簡直是排山倒海。下面是一個典型的對象集合,用裝飾者來將功能結合起來,以讀取文件數據:
超類:InputStream
組件:FileInputStream、StringBufferInputStream、ByteArrayInputStream
抽象裝飾者:FilterInputStream
具體裝飾者:PushBackInputStream、BufferedInputStream、DataInputStream、LineNumberInputStream
觀察者模式:
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update(float temp, float humidity, float pressure);
}
public interface DispalyElement {
public void dispaly();
}
public class WeatherData implements Subject {
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
//通知每一個觀察者
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
//測試代碼
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay =
new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80,65,30.4f);
}
}
裝飾者模式:
//抽象類
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
//CondimentDecorator必須能取代Beverage,所以將CondimentDecorator必須能取代Beverage,所以將擴展成Beverage類擴展成Beverage類
public abstract class CondimentDecorator extends Beverage {
//所有調料裝飾者必須重新實現getDescription()方法
public abstract String getDescription();
}
//飲料代碼擴展自Beverage
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
//裝飾者
public class Soy extends CondimentDecorator {
Beverage beverage;//記錄被裝飾者
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
return .15 + beverage.cost();
}
}
//測試代碼
public class StarbuzzCoffee {
public static void main(String args[]) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription()
+ " $" + beverage.cost());
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);//層層裝飾
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription()
+ " $" + beverage2.cost());
Beverage beverage3 = new HouseBlend();
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
System.out.println(beverage3.getDescription()
+ " $" + beverage3.cost());
}
}