最近補一下設計模式相關的知識,關於觀察者設計模式主要從以下幾個方面來學習,具體如下:
- 什麼是觀察者設計模式
- 關鍵概念理解
- 通知觀察者的方式
- 觀察者模式的實現
- 觀察者模式的優缺點
- 使用場景
什麼是觀察者設計模式#
觀察者模式(Observer)是軟體設計模式的一種,定義了物件之間一種一對多的關係,也就是當一個物件數據發生變化時,會通知與之依賴的其他物件,以相應其數據變化,這種當目標物件數據發生變化時,與之對應的觀察者物件數據隨之發生變化的,具有一對多通知關係的設計模式叫做觀察者設計模式。
關鍵概念理解#
觀察者設計模式中主要區分兩個概念:
- 觀察者:指觀察者物件,也就是消息的訂閱者;
- 被觀察者:指要觀察的目標物件,也就是消息的發布者。
通知觀察者的方式#
當被被觀察者數據發生變化時,主要通過兩種方式通知觀察者,具體如下:
- 推:消息以類似廣播的形式通知觀察者,觀察者只能被動、無條件接受;
- 拉:接收到被觀察者的通知,可以自主決定獲取消息。
觀察者模式的實現#
下面通過兩種方式實現觀察者設計模式的實現,具體如下:
- 手寫觀察者設計模式
- Java API 提供的觀察者設計模式 使用 Java API 提供的 Observer 和 Observeable 實現觀察者模式
手寫觀察者模式#
首先創建被觀察者,具體如下:
/**
* 觀察者要觀察的目標物件
* @author jzman
*/
public abstract class Subject {
protected ArrayList<Observer> observerList = new ArrayList<>();
//表示觀察者對目標物件(被觀察者)開始觀察
public void registerObserver(Observer obs) {
observerList.add(obs);
}
//表示取消某觀察者對目標物件(被觀察者)的觀察
public void unRegisterObserver(Observer obs) {
observerList.remove(obs);
}
//當目標物件(被觀察者)的狀態發生變化時,及時更新觀察者的狀態
public void notifyAllObserver(){
for (Observer observer : observerList) {
observer.update(this);
}
}
}
創建具體的被觀察者,具體如下:
/**
* 具體的目標物件(被觀察者)
* @author jzman
*/
public class ConcreteSubject extends Subject{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
//當數據發生變化時通知其他的觀察者
notifyAllObserver();
}
}
然後,為了統一方便,定義觀察者接口,具體如下:
/**
* 觀察者統一接口
* @author jzman
*/
public interface Observer {
void update(Subject subject);
}
然後,創建具體的觀察者,具體如下:
/**
* 具體的觀察者
* @author jzman
*/
public class ConcreteObserver implements Observer{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
@Override
public void update(Subject subject) {
//獲取目標物件的數據變化,同時更新當前觀察者
ConcreteSubject concreteSubject = (ConcreteSubject)subject;
state = concreteSubject.getState();
}
}
最後,測試觀察者設計模式,具體如下:
/**
* Main
* @author jzman
*/
public class Client {
public static void main(String[] args) {
//創建具體的目標物件(被觀察者)
ConcreteSubject concreteSubject = new ConcreteSubject();
//創建多個具體的觀察者
ConcreteObserver obs1 = new ConcreteObserver();
ConcreteObserver obs2 = new ConcreteObserver();
ConcreteObserver obs3 = new ConcreteObserver();
//讓觀察者觀察目標物件(被觀察者)的數據變化
concreteSubject.observerList.add(obs1);
concreteSubject.observerList.add(obs2);
concreteSubject.observerList.add(obs3);
//改變某個目標物件(被觀察者)的數據
concreteSubject.setState(10);
//觀察者數據是否與被觀察者數據變化一致
System.out.println("觀察者obs1:"+obs1.getState());
System.out.println("觀察者obs2:"+obs2.getState());
System.out.println("觀察者obs3:"+obs3.getState());
}
}
顯然,執行結果肯定如下:
觀察者obs1:10
觀察者obs2:10
觀察者obs3:10
通過對目標物件數據的改變,更新了與之相對應的觀察者的數據,實現了消息的訂閱和發送。
Java API 提供的觀察者設計模式#
Java API 提供的觀察者設計模式主要通過 Observer 和 Observeable 來實現,首先創建一個類繼承 Observeable 作為被觀察者,具體如下:
/**
* 被觀察者(目標物件)
* @author jzman
*/
public class ConcreteSubject extends Observable{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
//表示數據已經發生變化
setChanged();
//具體的目標物件數據變化的時候通知觀察者
notifyObservers(state);
}
}
然後,創建一個類繼承 Observer 作為觀察者,具體如下:
/**
* 觀察者
* @author jzman
*/
public class ConcreteObserver implements Observer{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
@Override
public void update(Observable arg0, Object arg1) {
ConcreteSubject concreteSubject = (ConcreteSubject) arg0;
//根據目標物件(被觀察者)的數據變化更新當前觀察者的數據
this.state = concreteSubject.getState();
}
}
最後,測試觀察者設計模式,具體如下:
/**
* 測試觀察者設計模式
* @author jzman
*/
public class Client {
public static void main(String[] args) {
ConcreteSubject concreteSubject = new ConcreteSubject();
ConcreteObserver obs1 = new ConcreteObserver();
ConcreteObserver obs2 = new ConcreteObserver();
ConcreteObserver obs3 = new ConcreteObserver();
concreteSubject.addObserver(obs1);
concreteSubject.addObserver(obs2);
concreteSubject.addObserver(obs3);
concreteSubject.setState(100);
System.out.println("觀察者obs1:"+obs1.getState());
System.out.println("觀察者obs2:"+obs2.getState());
System.out.println("觀察者obs3:"+obs3.getState());
}
}
顯然,執行結果肯定如下:
觀察者obs1:100
觀察者obs2:100
觀察者obs3:100
觀察者模式的優缺點#
- 優點:觀察者與被觀察者抽象耦合,可定義一種穩定的消息觸發機制。
- 缺點:如果被觀察者有多個間接的觀察者,消息的傳遞將消耗更多時間,如果觀察者與被觀察者之間循環依賴,最終會導致系統崩潰。
使用場景#
觀察者設計模式在開發中使用比較廣泛,主要有以下幾個場景,具體如下:
- 如遊戲、聊天等過程中消息的從服務端轉發給客戶端的過程
- Android 中的廣播機制以及 ListView 中通知數據發生變化時也是觀察者設計模式
- 訂閱類相關的系統,如當訂閱的主題有更新,訂閱者就會同步訂閱的文章。
觀察者設計模式到此結束。