一個主題可能有多個觀察者,例如技術分析 ( 觀察者1 ),當日走勢 (觀察者 2) 等多個觀察者關注相同的主題。
因為上一篇的設計沒有 Observer 抽象基礎類別,為了滿足多個觀察者的需求,或許會想到可以新增成員變數 ViewType 來區分不同的觀察者,擁有 $View_TA 的是技術分析,而擁有 $View_Tick 的是當日走勢。
enum class ViewType{ $View_TA, // 技術分析 $View_Tick // 當日走勢};
class CObserver final // 台積電資料的觀察者{public: CObserver(ViewType eType) : m_eType(eType) {}public: void Update(CTSMCStockSubject* pSubject) {}private: ViewType m_eType;};
int main(){ auto ob1 = std::make_shared<CObserver>(ViewType::$View_TA); // 技術分析 auto ob2 = std::make_shared<CObserver>(ViewType::$View_Tick); // 當日走勢 CTSMCStockSubject subject; subject.Subscribe(ob1); subject.Subscribe(ob2); subject.Notify(); subject.Unsubscribe(ob2); subject.Unsubscribe(ob1); return 0;}
但這樣勢必 CObserver 內會有許多 if … else … 的判斷敘述去處理 $View_TA 及 $View_Tick 的分支 case,或許還有人進一步想到用狀態模式 (State pattern) 來重構 CObserver。
其實這些都是本末倒置,正確做法就是需要有 Observer 抽象基礎類別的存在,不同的觀察者繼承此抽象基礎類別並實作之,對應的處理邏輯寫在各自的衍生類別內,消除了 CObserver 內可能的 if (ViewType == $View_TA) else … 的判斷處理。
class IObserver // Observer 抽象基礎類別{public: virtual ~IObserver() = 0 {}public: virtual void Update(CTSMCStockSubject* pSubject) = 0;};
// 技術分析class CTAViewObserver : public IObserver{public: virtual void Update(CTSMCStockSubject* pSubject) override {}};
// 商品盤勢class CTickViewObserver : public IObserver{public: virtual void Update(CTSMCStockSubject* pSubject) override {}};
CTSMCStockSubject 類別內所有的 CObserver 也要修改成 IObserver。
class CTSMCStockSubject final // 台積電資料的主題{public: void Subscribe(const std::shared_ptr<IObserver>& ob) { m_observers.emplace(ob); } void Unsubscribe(const std::shared_ptr<IObserver>& ob) { m_observers.erase(ob); } void Notify() { for (auto& ob : m_observers) { ob->Update(this); } }private: std::set<std::shared_ptr<IObserver>> m_observers;};
使用方式改為直接 new 出對應的 class,不必再使用 ViewType 區分,程式更為清楚明確。
int main(){ auto ob1 = std::make_shared<CTAViewObserver>(); // 技術分析 auto ob2 = std::make_shared<CTickViewObserver>(); // 當日走勢 CTSMCStockSubject subject; subject.Subscribe(ob1); subject.Subscribe(ob2); subject.Notify(); subject.Unsubscribe(ob2); subject.Unsubscribe(ob1);}

留言
張貼留言