跟著GPT學設計模式之觀察者模式

你好,這里是codetrend專欄“跟著GPT學設計模式”。

引言

觀察者模式(Observer Pattern)是一種行為型設計模式,它定義了對象之間的一對多依賴關系,使得當一個對象的狀態(tài)發(fā)生改變時,其依賴對象都能夠收到通知并自動更新。

觀察者模式(Observer Design Pattern)也被稱為發(fā)布訂閱模式(Publish-Subscribe Design Pattern)。一般情況下,被依賴的對象叫作被觀察者(Observable),依賴的對象叫作觀察者(Observer)。

不過,在實際的項目開發(fā)中,這兩種對象的稱呼是比較靈活的,有各種不同的叫法,比如:Subject-Observer、Publisher-Subscriber、Producer-Consumer、EventEmitter-EventListener、Dispatcher-Listener。

在觀察者模式中,有兩個主要角色:主題(Subject)和觀察者(Observer)。主題是被觀察的對象,它維護了一個觀察者列表,并提供方法用于添加、刪除和通知觀察者。

觀察者是監(jiān)聽主題的對象,它定義了一個更新的方法,在主題狀態(tài)改變時被調用。

觀察者模式的一般工作流程:

  • 主題對象維護一個觀察者列表,并提供方法用于注冊、注銷和通知觀察者。
  • 觀察者對象實現(xiàn)一個更新方法,用于在主題狀態(tài)改變時被調用。
  • 當主題的狀態(tài)發(fā)生改變時,它會遍歷觀察者列表,調用每個觀察者的更新方法。
  • 觀察者根據(jù)接收到的通知進行相應的操作,以使自身狀態(tài)與主題保持一致。

使用 Mermaid 語法類圖展示觀察者模式的示意圖如下:

classDiagram
    class Subject {
        + attach(Observer observer)
        + detach(Observer observer)
        + notifyObservers()
        # observers: Observer[]
    }

    class Observer {
        + update()
    }

    class ConcreteSubject {
        - state
        + getState()
        + setState(state)
    }

    class ConcreteObserver {
        + update()
    }

    Subject <|-- ConcreteSubject
    Subject "1" --> "*" Observer
    Observer <|-- ConcreteObserver
    ConcreteSubject --> ConcreteObserver
  • Subject 是主題類,包含了添加、刪除和通知觀察者的方法。observers 是一個觀察者列表,用于存儲注冊的觀察者對象。
  • Observer 是觀察者類,定義了一個 update() 方法,用于在主題狀態(tài)改變時被調用。
  • ConcreteSubject 是具體主題類,繼承自 Subject,它有一個額外的 state 屬性,表示當前狀態(tài),并提供了獲取和設置狀態(tài)的方法。
  • ConcreteObserver 是具體觀察者類,繼承自 Observer,實現(xiàn)了 update() 方法,根據(jù)主題狀態(tài)的改變來更新自身狀態(tài)。

這個類圖展示了觀察者模式的關鍵組件及它們之間的關系。主題與觀察者之間是一對多的關系,主題可以有多個觀察者。

當主題狀態(tài)改變時,它會通過通知方法 notifyObservers() 來遍歷觀察者列表,并依次調用每個觀察者的 update() 方法,從而實現(xiàn)觀察者的更新操作。

觀察者模式的使用場景

觀察者模式在實際應用中有很多場景,以下是一些觀察者模式的應用場景的舉例:

  • GUI 事件處理:在圖形用戶界面(GUI)中,觀察者模式被廣泛應用于事件處理機制。當用戶執(zhí)行某個操作時,比如點擊按鈕或輸入文本,這些操作會觸發(fā)相應的事件。事件作為主題被通知給注冊的觀察者,觀察者可以根據(jù)事件類型做出相應的響應,例如更新界面、執(zhí)行特定邏輯等。
  • 訂閱/發(fā)布模式:觀察者模式也常被稱為訂閱/發(fā)布模式。在發(fā)布者-訂閱者系統(tǒng)中,發(fā)布者充當主題的角色,訂閱者則扮演觀察者的角色。發(fā)布者負責發(fā)布消息,訂閱者訂閱感興趣的消息類型,并在消息到達時執(zhí)行相應的操作。這種模式廣泛應用于消息隊列系統(tǒng)、事件總線等。
  • 消息通知系統(tǒng):觀察者模式也可以用于構建消息通知系統(tǒng)。例如,一個新聞平臺可以作為主題,用戶可以選擇訂閱感興趣的新聞類別作為觀察者。當新聞發(fā)布時,平臺會通知所有訂閱了該類別的用戶,并將新聞推送給他們。
  • 游戲開發(fā)中的事件管理:在游戲開發(fā)中,觀察者模式常被用于事件管理。例如,游戲角色之間的互動和協(xié)作可以通過觀察者模式實現(xiàn)。一個角色可以作為主題,其他角色可以注冊為觀察者。當主題(例如敵人角色)發(fā)生改變時,通知所有觀察者(例如友方角色)并執(zhí)行相應的行為。

實際上觀察者模式非常靈活,適用于很多具有發(fā)布-訂閱關系的場景。它提供了一種松耦合的設計方式,使得主題和觀察者能夠獨立變化,并保持一致性。

觀察者模式使用注意事項

  • 角色和職責:觀察者模式中包括主題(Subject)和觀察者(Observer)兩個核心角色。主題負責管理觀察者的注冊、注銷以及通知操作,而觀察者則定義了接收更新通知并執(zhí)行相應操作的方法。了解每個角色的職責和關系對于正確使用觀察者模式非常重要。
  • 主題狀態(tài)管理:主題在觀察者模式中起到承載和管理狀態(tài)的作用。當主題狀態(tài)發(fā)生變化時,需要通知所有觀察者。因此,需要合理設計和管理主題的狀態(tài),并及時觸發(fā)通知操作。
  • 多線程安全性:在多線程環(huán)境下使用觀察者模式時,需要考慮線程安全性。例如,在主題狀態(tài)變化時,可能會遇到多個線程同時修改主題狀態(tài)或觸發(fā)通知的情況。需要采取相應的同步措施或使用線程安全的容器來確保并發(fā)訪問的正確性。
  • 事件傳遞方式:觀察者模式中,主題向觀察者傳遞更新通知的方式可以是同步或異步的。在同步方式下,主題在通知觀察者后會等待觀察者執(zhí)行完相應操作,才會繼續(xù)執(zhí)行;而在異步方式下,主題通知觀察者后立即繼續(xù)執(zhí)行,觀察者的更新操作在后臺進行。了解不同的事件傳遞方式對系統(tǒng)行為和性能的影響是重要的。

觀察者模式編程示例

下面通過一段代碼來說明觀察者模式的實現(xiàn)。

import java.util.ArrayList;
import java.util.List;

// 主題接口
interface Subject {
    void attach(Observer observer);
    void detach(Observer observer);
    void notifyObservers();
}

// 觀察者接口
interface Observer {
    void update();
}

// 具體主題類
class ConcreteSubject 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 notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }

    // 具體主題類的其他方法
    // ...
}

// 具體觀察者類
class ConcreteObserver implements Observer {
    @Override
    public void update() {
        System.out.println("觀察者收到更新通知,執(zhí)行相應操作。");
    }
}

public class ObserverPatternExample {
    public static void main(String[] args) {
        // 創(chuàng)建具體主題對象
        ConcreteSubject subject = new ConcreteSubject();

        // 創(chuàng)建具體觀察者對象
        ConcreteObserver observer1 = new ConcreteObserver();
        ConcreteObserver observer2 = new ConcreteObserver();

        // 注冊觀察者
        subject.attach(observer1);
        subject.attach(observer2);

        // 主題發(fā)生改變時,通知觀察者
        subject.notifyObservers();
    }
}

在上述示例中定義了一個 Subject 接口和一個 Observer 接口,分別表示主題和觀察者。

ConcreteSubject 是具體的主題類,實現(xiàn)了 Subject 接口,并包含了維護觀察者列表、添加/刪除觀察者以及通知觀察者的方法。

ConcreteObserver 是具體的觀察者類,實現(xiàn)了 Observer 接口,并在 update() 方法中定義了觀察者接收到更新通知時的操作。

在 main() 方法中創(chuàng)建了具體的主題對象 ConcreteSubject,以及兩個具體的觀察者對象 observer1 和 observer2。

然后通過 attach() 方法將觀察者注冊到主題中,然后調用 notifyObservers() 方法通知所有的觀察者。當主題發(fā)生改變時,所有觀察者都會收到更新通知,并執(zhí)行相應的操作。

以上內容基于 GPT 創(chuàng)建和整理。

關于作者

來自一線全棧程序員nine的探索與實踐,持續(xù)迭代中。

歡迎關注或者點個贊~

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容