觀察者模式定義物件間一對多依賴,當主題狀態改變時,自動通知所有已註冊觀察者。此模式廣泛應用於事件處理系統、MVC 架構的 Model-View 同步、訊息推播等場景。C++ 雖無介面關鍵字,但可用純虛函數抽象類別模擬介面,配合多型實現靈活的訂閱/發布機制。
// 前向宣告
class Observer;
class Subject;
// 主題抽象介面
class Subject {
public:
virtual ~Subject() = default;
virtual void attach(Observer* o) = 0; // 訂閱
virtual void detach(Observer* o) = 0; // 退訂 (補充)
virtual void notify() = 0; // 通知所有觀察者
virtual void setWeather(const std::string& str) = 0;
virtual std::string getWeather() const = 0;
};
// 觀察者抽象介面
class Observer {
public:
virtual ~Observer() = default;
virtual std::string getName() const = 0;
virtual void update(Subject* s) = 0; // 接收通知
};
class WeatherStation : public Subject {
private:
std::string weather_;
std::list observers_;
public:
void attach(Observer* o) override {
observers_.push_back(o);
}
void detach(Observer* o) override {
observers_.remove(o);
}
void notify() override {
for (auto* obs : observers_) {
obs->update(this);
}
}
void setWeather(const std::string& str) override {
weather_ = str;
notify(); // 狀態變更即通知
}
std::string getWeather() const override { return weather_; }
};
class Satellite : public Observer {
private:
std::string name_;
public:
explicit Satellite(const std::string& name) : name_(name) {}
std::string getName() const override { return name_; }
void update(Subject* s) override {
std::cout << name_ << " 收到天氣更新: " << s->getWeather() << '\n';
}
};
int main() {
WeatherStation station;
// 建立四顆衛星觀察者
Satellite s1("風雲一號"), s2("風雲二號"), s3("風雲三號"), s4("風雲四號");
// 訂閱
station.attach(&s1);
station.attach(&s2);
station.attach(&s3);
station.attach(&s4);
// 模擬天氣變化
station.setWeather("晴朗");
station.setWeather("雷陣雨");
station.setWeather("多雲");
return 0;
}
風雲一號 收到天氣更新: 晴朗
風雲二號 收到天氣更新: 晴朗
風雲三號 收到天氣更新: 晴朗
風雲四號 收到天氣更新: 晴朗
風雲一號 收到天氣更新: 雷陣雨
風雲二號 收到天氣更新: 雷陣雨
風雲三號 收到天氣更新: 雷陣雨
風雲四號 收到天氣更新: 雷陣雨
風雲一號 收到天氣更新: 多雲
風雲二號 收到天氣更新: 多雲
風雲三號 收到天氣更新: 多雲
風雲四號 收到天氣更新: 多雲
std::list 或 std::vector 儲存觀察者指標;list 適合頻繁增刪,vector 遍歷較快。std::shared_ptr<Observer>。observers_ 容器,或使用無鎖資料結構。getWeather() 取資料);若資料量大,可改推模型 直接在 update 參數傳遞資料。
struct WeatherData {
float temperature;
float humidity;
float pressure;
};
class AdvancedStation : public Subject {
WeatherData data_;
std::list obs_;
public:
void setData(const WeatherData& d) { data_ = d; notify(); }
const WeatherData& getData() const { return data_; }
// ... attach/detach/notify 同前
};
class DisplayBoard : public Observer {
void update(Subject* s) override {
auto* station = dynamic_cast(s);
if (station) {
auto d = station->getData();
std::cout << "溫度:" << d.temperature << " 濕度:" << d.humidity << '\n';
}
}
};
觀察者模式以抽象介面解耦主題與觀察者,實現動態訂閱與廣播通知。C++ 透過純虛函數與多型優雅實現此模式,配合標準庫容器與智慧指標,可構建健壯、可擴充的事件驅動系統。掌握其核心結構與變體 (推/拉、執行緒安全、生命週期策略) 是 C++ 架構師必備技能。