行為型設計模式 – 觀察者模式詳解
基本介紹
觀察者模式(Observer Pattern)又被稱為發布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式,屬於行為型模式的一種。
定義了一種一對多的模式,多個觀察者監視一個主題,當主題狀態發生變化時,會通知所有觀察者。觀察者之間沒有互相聯繫,可以增加、刪除觀察者,易於管理和擴展。
模式結構
Subject(抽象主題):和觀察者是一對多的關係,即一個主題可以綁定多個觀察者
ConcreteSubject(具體主題):實現抽象主題的方法,當主題內部發生變化時,通知所有綁定的觀察者
Observer(抽象觀察者):定義了更新的方法,當主題有變化時,通過此方法更新自己
ConcreteObserver(具體觀察者):實現抽象觀察者,實現更新方法
舉例說明
以用戶和頻道為例,當頻道有新的消息時,會將通知發送給所有訂閱了該頻道的用戶
1、抽象觀察者,定義了一個更新的方法
public interface Observer {
void update(String message);
}
2、具體觀察者:用戶,定義一個名稱屬性,實現抽象觀察者的方法
public class UserObserver implements Observer {
private String name;
public UserObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + "收到通知:" + message);
}
}
3、抽象主題,有添加、刪除、通知功能
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notify(String message);
}
4、具體主題:新聞頻道,定義一個 List 存儲觀察者,通知時循環遍歷集合進行通知
public class NewsSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notify(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
5、測試類
public class Client {
@Test
public void test() {
Subject newsSubject = new NewsSubject();
Observer user1 = new UserObserver("小龍");
Observer user2 = new UserObserver("小鳳");
newsSubject.attach(user1);
newsSubject.attach(user2);
newsSubject.notify("新聞頻道發布了一條緊急新聞");
}
}
6、運行結果
小龍收到通知:新聞頻道發布了一條緊急新聞
小鳳收到通知:新聞頻道發布了一條緊急新聞
7、如果我們需要添加其它頻道也非常的方便,只需要添加一個具體主題(比如體育頻道),其它業務程式碼無需改動,測試類中將用戶註冊進去即可。
模式分析
優點
- 耦合性低,讓耦合的雙方都依賴於抽象,當發生變化時,雙方互不干擾
- 擴展性高,添加具體主題或是添加具體觀察者,都無需修改其他程式碼
缺點
- 如果一個主題有很多直接或間接的觀察者,則通知的過程會花費很多時間
- 如果主題和觀察者之間有循環依賴,可能會造成程式死循環導致系統崩潰
適用場景
- 觀察者模式在軟體開發中應用非常廣泛,比如電商系統可以在執行發送操作後給用戶多個發送商品打折資訊,遊戲中隊友犧牲將給所有成員提示等等,凡是涉及到一對一或者一對多的對象交互場景都可以使用觀察者模式。