前言
觀察者模式又被成為發布-訂閱模式, 屬于行為型設計模式的一種,是一個在項目中經常使用的模式。
定義
定義對象間一種一對多的依賴關系,每當一個對象改變狀態時,則所有依賴它的對象都會得到通知并被自動更新。
使用場景
- 關聯行為場景。需要注意的是,關聯行為是可拆分的,而不是“組合”關系。
- 事件多觸發場景。
- 跨系統的消息交換場景,如消息隊列、事件總線的處理機制。
角色
- Subject:抽象主題(抽象被觀察者)。抽象主題角色把所有觀察者對象保存在一個集合里,每個主題都可以有任意數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象。
- ConcreteSubject:具體主題(具體被觀察者)。該角色將有關狀態存入具體觀察者對象,在具體主題的內部狀態發生改變時,給所有注冊過的觀察者發送通知。
- Observer:抽象觀察者,是觀察者的抽象類。它定義一個更新接口,使得在得到主題更改通知時更新自己。
- ConcrereObserver:具體觀察者,實現抽象觀察者定義的更新接口,以便在得到主題更改通知時更新自身的狀態。
觀察者模式的簡單實現
微信公眾號場景:假設微信用戶就是觀察者,微信公眾號是被觀察者,有多個微信用戶關注了“程序員”這個公眾號。當這個公眾號更新時就會通知這些訂閱的用戶。
- 抽象觀察者:里面定義一個更新方法。
public interface Observer {
void update(String message);
}
- 具體觀察者:微信用戶是觀察者,里面實現了更新的方法。
public class WeChatUser implements Observer {
private String name;
public WeChatUser(String name){
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " " + message);
}
}
-
抽象被觀察者:被觀察者,提供
attach
、detach
、notify
三個方法。
public interface Subject {
/**
* 增加訂閱者
* @param observer
*/
void attach(Observer observer);
/**
* 刪除訂閱者
* @param observer
*/
void detach(Observer observer);
/**
* 通知訂閱者更新消息
* @param message
*/
void notify(String message);
}
- 具體被觀察者:微信公眾號具體主題(具體被觀察者),里面存儲了訂閱該公眾號的微信用戶,并實現了抽象主題中的方法。
public class SubscriptionSubject implements Subject {
private List<Observer> weChatUserList = new ArrayList<Observer>();
@Override
public void attach(Observer observer) {
weChatUserList.add(observer);
}
@Override
public void detach(Observer observer) {
weChatUserList.remove(observer);
}
@Override
public void notify(String message) {
for(Observer observer : weChatUserList){
observer.update(message);
}
}
}
- 客戶端調用。
public class Client {
public static void main(String[] args) {
SubscriptionSubject mSubscriptionSubject = new SubscriptionSubject();
//創建微信用戶
WeChatUser user1 = new WeChatUser("用戶1");
WeChatUser user2 = new WeChatUser("用戶2");
WeChatUser user3 = new WeChatUser("用戶3");
//訂閱公眾號
mSubscriptionSubject.attach(user1);
mSubscriptionSubject.attach(user2);
mSubscriptionSubject.attach(user3);
//公眾號更新發出消息給訂閱的微信用戶
mSubscriptionSubject.notify("公眾號有更新內容了");
}
}
優缺點
優點
- 觀察者和被觀察者之間是抽象耦合,容易擴展。
- 方便建立一套觸發機制。
缺點
- 在應用觀察者模式時需要考慮一下開發效率和運行效率的問題。程序中包括一個被觀察者和多個觀察者,開發、調試等內容比較復雜,而且在
Java
中消息的通知一般是有執行順序的,那么一個觀察者卡頓,會影響整體的執行效率,這種情況下一般會采用異步方式。