觀察者模式要點:
1.觀察者模式定義了對象之間一對多的關係
2.主題(也就是可觀察者)用一個共同的接口來更新觀察者
3.觀察者和可觀察者之間用鬆耦合方式,可觀察者不知道觀察者的細節,只知道觀察者實現了觀察者接口
4.使用此模式時,你可從被觀察者處推或拉數據
5.有多個觀察者時,不可以以來特定的通知次序
6.java有多種觀察者模式的實現,包括通用的java.util.Observable
7.要注意java.util.Observable實現上所來來的一些問題
8.Swing大量使用觀察者模式,許多GUI框架也是如此
9.此模式也被應用在許多地方,例如:JavaBean、RMI
觀察者模式:在對象之間定義一對多的依賴,這樣一來,檔一個對象改變狀態,依賴它的對象都會收到通知,並自動更新。
結構總結:從具體主題角色指向抽象觀察者角色的合成關係,代表具體主題對象可以有任意多個對抽象觀察者對象的引用。之所以使用抽象觀察者而不是具體觀察者,意味着主題對象不需要知道引用了哪些ConcreteObserver類型,而只知道抽象Observer類型。這就使得具體主題對象可以動態地維護一系列的對觀察者對象的引用,並在需要的時候調用每一個觀察者共有的Update()方法。這種做法叫做"針對抽象編程"。
觀察者模式的優缺點:
Observer模式的優點是實現了表示層和數據邏輯層的分離,並定義了穩定的更新消息傳遞機制,類別清晰,並抽象了更新接口,使得可以有各種各樣不同的表示層(觀察者)。但是其缺點是每個外觀對象必須繼承這個抽像出來的接口類,這樣就造成了一些不方便,比如有一個別人寫的外觀對象,並沒有繼承該抽象類,或者接口不對,我們又希望不修改該類直接使用它。雖然可以再應用Adapter模式來一定程度上解決這個問題,但是會造成更加複雜煩瑣的設計,增加出錯機率。
觀察者模式的效果有以下幾個優點:
(1)觀察者模式在被觀察者和觀察者之間建立一個抽象的耦合。被觀察者角色所知道的只是一個具體現察者聚集,每一個具體現察者都符合一個抽象觀察者的接口。被觀察者並不認識任何一個具體觀察者,它只知道它們都有一個共同的接口。由於被觀察者和觀察者沒有緊密地耦合在一起,因此它們可以屬於不同的抽象化層次。
(2)觀察者模式支持廣播通信。被觀察者會向所有的登記過的觀察者發出通知。
觀察者模式有下面的一些缺點:
(1)如果一個被觀察者對象有很多直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
(2)如果在被觀察者之間有循環依賴的話,被觀察者會觸發它們之間進行循環調用,導致系統崩潰。在使用觀察考模式時要特別注意這一點。
(3)如果對觀察者的通知是通過另外的線程進行異步投遞的話,系統必須保證投遞是以自恰的方式進行的。
(4)雖然觀察者模式可以隨時使觀察者知道所觀察的對象發生了變化,但是觀察者模式沒有相應的機制使觀察者知道所觀察的對象是怎麼發生變化
public interface Subject {
public void register(Observer observer);
public void remove(Observer observer);
public void notifiedObserver();
}
public interface Observer {
public void update(float temp, float humidity, float pressure);
}
import java.util.*;
public class WeatherDate implements Subject {
private float temp;
private float humidity;
private float pressure;
List list = new ArrayList();
public void register(Observer observer) {
list.add(observer);
}
public void remove(Observer observer) {
int i = list.indexOf(observer);
if (i >= 0) {
list.remove(i);
}
}
public void notifiedObserver() {
for (int i = 0; i < list.size(); i++) {
Observer observer = (Observer) list.get(i);
observer.update(temp, humidity, pressure);
}
}
public void changeDate() {
notifiedObserver();
}
public void setMeasure(float temp, float humidity, float pressure) {
this.temp = temp;
this.humidity = humidity;
this.pressure = pressure;
changeDate();
}
}
public class CurrentConditionsDisplay implements Observer {
private float temp;
private float humidity;
private float pressure;
private WeatherDate wd ;
public CurrentConditionsDisplay(WeatherDate wd){
this.wd = wd;
wd.register(this);
}
public void update(float temp, float humidity, float pressure) {
this.temp = temp;
this.humidity = humidity;
this.pressure = pressure;
display();
}
public void display(){
System.out.println("Current condition:"+ temp+"F degrees and" +humidity +"%humidty");
}
}
public class WeatherStation {
public static void main(String[] args) {
WeatherDate weatherdate = new WeatherDate();
CurrentConditionsDisplay condition = new CurrentConditionsDisplay(
weatherdate);
weatherdate.setMeasure(80, 65, 70);
}
}