1. 程式人生 > >android 開發設計模式---觀察者模式

android 開發設計模式---觀察者模式

嚴格 oid line eventbus 否則 post vat 關系 lock

  • 情景1

    有一種短信服務,比如天氣預報服務,一旦你訂閱該服務,你只需按月付費,付完費後,每天一旦有天氣信息更新,它就會及時向你發送最新的天氣信息。

  • 情景2

    雜誌的訂閱,你只需向郵局訂閱雜誌,繳納一定的費用,當有新的雜誌時,郵局會自動將雜誌送至你預留的地址。

觀察上面兩個情景,有一個共同點,就是我們無需每時每刻關註我們感興趣的東西,我們只需做的就是訂閱感興趣的事物,比如天氣預報服務,雜誌等,一旦我們訂閱的事物發生變化,比如有新的天氣預報信息,新的雜誌等,被訂閱的事物就會即時通知到訂閱者,即我們。而這些被訂閱的事物可以擁有多個訂閱者,也就是一對多的關系。當然,嚴格意義上講,這個一對多可以包含一對一,因為一對一是一對多的特例,沒有特殊說明,本文的一對多包含了一對一。

現在你反過頭來看看觀察者模式的定義,你是不是豁然開朗了。

然後我們看一下觀察者模式的幾個重要組成。

  • 觀察者,我們稱它為Observer,有時候我們也稱它為訂閱者,即Subscriber 如sdk,廣播的發送 EventBus.post 等
  • 被觀察者,我們稱它為Observable,即可以被觀察的東西,有時候還會稱之為主題,即Subject

至於觀察者模式的具體實現,這裏帶帶大家實現一下場景一,其實java中提供了Observable類和Observer接口供我們快速的實現該模式,但是為了加深印象,我們不使用這兩個類。

場景1中我們感興趣的事情是天氣預報,於是,我們應該定義一個Weather實體類。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Weather {
private String description;

public Weather(String description) {
this.description = description;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

@Override
public String toString() {
return "Weather{" +
"description=‘" + description + ‘\‘‘ +
‘}‘;
}
}

然後定義我們的被觀察者,我們想要這個被觀察者能夠通用,將其定義成泛型。內部應該暴露register和unregister方法供觀察者訂閱和取消訂閱,至於觀察者的保存,直接用ArrayList即可,此外,當有主題內容發送改變時,會即時通知觀察者做出反應,因此應該暴露一個notifyObservers方法,以上方法的具體實現見如下代碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Observable<T> {
List<Observer<T>> mObservers = new ArrayList<Observer<T>>();

public void register(Observer<T> observer) {
if (observer == null) {
throw new NullPointerException("observer == null");
}
synchronized (this) {
if (!mObservers.contains(observer))
mObservers.add(observer);
}
}

public synchronized void unregister(Observer<T> observer) {
mObservers.remove(observer);
}

public void notifyObservers(T data) {
for (Observer<T> observer : mObservers) {
observer.onUpdate(this, data);
}
}

}

而我們的觀察者,只需要實現一個觀察者的接口Observer,該接口也是泛型的。其定義如下。

1
2
3
public interface Observer<T> {
void onUpdate(Observable<T> observable,T data);
}

一旦訂閱的主題發送變換就會回調該接口。

我們來使用一下,我們定義了一個天氣變換的主題,也就是被觀察者,還有兩個觀察者觀察天氣變換,一旦變換了,就打印出天氣信息,註意一定要調用被觀察者的register進行註冊,否則會收不到變換信息。而一旦不敢興趣了,直接調用unregister方法進行取消註冊即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Main {
public static void main(String [] args){
Observable<Weather> observable=new Observable<Weather>();
Observer<Weather> observer1=new Observer<Weather>() {
@Override
public void onUpdate(Observable<Weather> observable, Weather data) {
System.out.println("觀察者1:"+data.toString());
}
};
Observer<Weather> observer2=new Observer<Weather>() {
@Override
public void onUpdate(Observable<Weather> observable, Weather data) {
System.out.println("觀察者2:"+data.toString());
}
};

observable.register(observer1);
observable.register(observer2);


Weather weather=new Weather("晴轉多雲");
observable.notifyObservers(weather);

Weather weather1=new Weather("多雲轉陰");
observable.notifyObservers(weather1);

observable.unregister(observer1);

Weather weather2=new Weather("臺風");
observable.notifyObservers(weather2);

}
}

最後的輸出結果也是沒有什麽問題的,如下

觀察者1:Weather{description=’晴轉多雲’}
觀察者2:Weather{description=’晴轉多雲’}
觀察者1:Weather{description=’多雲轉陰’}
觀察者2:Weather{description=’多雲轉陰’}
觀察者2:Weather{description=’臺風’}

android 開發設計模式---觀察者模式