定義
觀察者設計模式是一個非常受歡迎的行為型模式,它允許物件間建立一對多的依賴關係。當一個物件的狀態改變時,所有依賴於它的物件都會收到通知。
關鍵字
以下,我們將透過 Solid State Drive (SSD) 和 Driver 的例子,來解釋觀察者模式
1.1 Subject
class Observer;
class Subject {
public:
    void addObserver(Observer* obs) {
        observers.push_back(obs);
    }
    void removeObserver(Observer* obs) {
        observers.erase(std::remove(observers.begin(), observers.end(), obs), observers.end());
    }
protected:
    void notify() {
        for (Observer* obs : observers) {
            obs->update();
        }
    }
private:
    vector<Observer*> observers;
};
1.2 Observer
class Observer {
public:
    virtual void update() = 0;
};
2.1 Concrete Subject
class SSD : public Subject {
public:
    void receiveData(std::string data) {
        this->data = data;
        notify();
    }
    std::string getData() const {
        return data;
    }
private:
    std::string data;
};
2.2 Concrete Observer
class KernelIODevice : public Observer {
public:
    KernelIODevice(SSD* drive) : drive(drive) {}
    void update() override {
        std::cout << "Kernel I/O Device updated with data: " << drive->getData() << std::endl;
    }
private:
    SSD* drive;
};
class Driver : public Observer {
public:
    Driver(SSD* drive) : drive(drive) {}
    void update() override {
        std::cout << "Driver processed the data: " << drive->getData() << std::endl;
    }
private:
    SSD* drive;
};
說明
int main() {
    SSD mySSD;
    KernelIODevice ioDevice(&mySSD);
    Driver ssdDriver(&mySSD);
    mySSD.addObserver(&ioDevice);
    mySSD.addObserver(&ssdDriver);
    mySSD.receiveData("Operating System Boot Sequence");
    return 0;
}
Output
Kernel I/O Device updated with data: Operating System Boot Sequence
Driver processed the data: Operating System Boot Sequence
小結
註: GoF 書中提到的 Pub-Sub 與我們現代軟體開發使用的 Pub-Sub 還是有些不同,不可完全視作等號!
發布者 (Publisher):
訂閱者 (Subscriber):
回到我們的 SSD 和 Kernel I/O Device, Driver 的例子,SSD 可以被視為發布者,而 Kernel I/O Device 和 Driver 是訂閱者。當 SSD 接收到新數據或命令時(即狀態改變),它會通知所有的訂閱者,這些訂閱者隨後可以執行各自的操作,如更新緩存或處理數據
[1]. https://notfalse.net/11/pub-sub-pattern
[2]. https://www.agilecaterpillar.com/blog/observer/