2010-08-31 35 views
3

首先,我知道有很好的實現(Qt,Boost,cpp-event等),但我問這個問題是因爲我想知道它是如何工作的!C++中事件系統的原理是什麼?

如果我理解正確,「事件系統」使用觀察者模式:一些對象正在觀察,等待某事發生......而其他人則發送信號。好吧。

所以,讓我們說,我有我的觀察類,有這樣的事情:

void Observer::getNotified() 
{ 
    // Do stuff 
} 

我的問題是:如何動態地管理應做什麼樣的東西?我見過很多人說不使用函數指針。對於我目前的需求,我可以做一個switch語句,一個枚舉類型,並選擇不同的行爲,但這並不令人滿意。所以,如果它不是函數指針,它是如何完成的?

回答

4

有可能有很多不同的實現(無論語言),但抽象的理念是:

  1. 有一個事件類型標識符知道至極事件被觀察的對象已經被解僱(也可以是無論什麼作品);
  2. 有一個在註冊對象中註冊的觀察者列表(或幾個,一個是事件類型?) - 假設觀察者是函子(函數指針或對象,它們像函數一樣)或者是具有已知接口的對象用虛擬方法來調用離子事件);
  3. 當事件被觸發時(通過調用被觀察對象上的函數),我們只需通過註冊了事件類型的觀察者列表並將事件信息(ID加上可能的數據)傳遞給觀察者來處理;

這裏是一個simplist實現:

enum EventType 
{ 
    Event_A, 
    Event_B, 
}; 

class Observer // for this example i'll suppose observer inherits this class 
{ 
    virtual void catchEvent(EventType e) = 0; // for sake of the example I just need the event type, not the data, but it's often required 

    virtual ~Observer(){}; // virtual base classes require this to work fine. 
}; 

class Observed 
{ 
     typedef std::vector<Observer*> ObserverList; 
     typedef std::map< EventType, ObserverList > ObserversTable; 
     ObserversTable m_observers; // we have observers for each event type 

public: 

    void addObserver(Observer& observer, EventType eType) 
    { m_observers[ eType ].push_back(observer); } // this is simplist, to say the least... 

    void sendEvent(EventType event) // here we send the event, it will be catched by observers 
    { // note : often this type of system is "buffered", but here we will process it immediatly as it's a simple example 

     ObserverList& observers = m_observers[ event ]; 
     for (ObserverList::iterator it = observers.begin(); it != observers.end(); ++it) 
     { 
       Observer* observer = *it; 
       observer->catchEvent(event); // here an observer receive the event 
     } 

    } 
}; 

這的確是一個基本的例子,但可以幫助你理解的想法。

+0

謝謝:它不太瞭解我的問題,但它也會非常有幫助。 – Raveline 2010-08-31 12:46:01

+0

它不直接回答,因爲正如我所說:有很多不同的實現可能(不管語言如何) 我已經實現了大量完全不同的方法來在C++中完成它(以及其他語言中的其他變體)和對每件事都很難使用特定的實現。 或者我可能不明白你的問題的確切點? :) – Klaim 2010-08-31 12:59:22

+1

@Raveline:再看一次,它確實回答你的問題:而不是使用函數指針,從接口(Observer)繼承。然後它顯示瞭如何動態管理應該完成什麼樣的東西。 – stefaanv 2010-08-31 13:00:58

1

請參閱Pete Goodliffe的excellent article,該路由根據要通知的事件類型路由到不同的方法。

如果您需要在單個事件類型中選擇操作,那麼通常您的代碼將根據通知中傳遞的數據進行選擇。

+0

有趣! +1 – Klaim 2010-08-31 12:24:56

+0

確實很有意思。我將從此開始,謝謝! – Raveline 2010-08-31 12:43:21