《Head First 設計模式》學習筆記——觀察者模式 + 裝飾者模式

裝飾者模式是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());
	}
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章