觀察者模式通常的叫法叫做訂閱 發佈模式,類似於報刊雜誌的訂閱,觀察者和被觀察者就是讀者和郵局的關係,讀者先要在郵局訂閱想要的報刊,當報刊發行時,郵局會將報刊郵寄到讀者家裡。觀察者(Observer)和被觀察者(Listener)也是這種關係,Observer將自己attach到Listener中,當 ...
觀察者模式通常的叫法叫做訂閱-發佈模式,類似於報刊雜誌的訂閱,觀察者和被觀察者就是讀者和郵局的關係,讀者先要在郵局訂閱想要的報刊,當報刊發行時,郵局會將報刊郵寄到讀者家裡。觀察者(Observer)和被觀察者(Listener)也是這種關係,Observer將自己attach到Listener中,當Listener觸發時Notify所有Observer.
作用
在觀察者模式中,被觀察者維護觀察者對象的集合,當被觀察者對象變化時,它會通知觀察者。觀察者模式主要是用於解決對象之間一對多的關係。
類視圖
實現
class Observer
{
public:
virtual ~Observer() {};
virtual void Update(const std::string &msg)= 0;
protected:
Observer(){};
};
class Listener
{
public:
virtual ~Listener() {};
void attach(Observer* obsvr)
{
m_observers.push_back(obsvr);
}
void remove(Observer* obsvr)
{
m_observers.remove(obsvr);
}
void notify(const std::string &msg)
{
list<Observer*>::iterator iter = m_observers.begin();
for(; iter != m_observers.end(); iter++)
(*iter)->Update(msg);
}
private:
list<Observer* > m_observers; //觀察者鏈表
};
class logRunner : public Listener
{
public:
virtual ~logRunner(){};
void addmsg(const std::string &msg)
{
nofity(msg);
}
}
class logGui : public Observer
{
public:
virtual ~Observer(){};
void Update(const std::string &msg)
{
cout<< "Gui log show : "<< msg <<endl;
}
}
class logFile : public Observer
{
public:
virtual ~Observer(){};
void Update(const std::string &msg)
{
cout<< "file log write : "<< msg <<endl;
}
}
class logDebug : public Observer
{
public:
virtual ~Observer(){};
void Update(const std::string &msg)
{
cout<< "Debug log out : "<< msg <<endl;
}
}
class logDataBase : public Observer
{
public:
virtual ~Observer(){};
void Update(const std::string &msg)
{
cout<< "DataBase log in : "<< msg <<endl;
}
}
int main()
{
logRunner Runner;
logGui gGui;
logFile gFile;
logDebug gDebug;
logDataBase gDataBase;
Runner.attach(&gGui);
Runner.attach(&gFile);
Runner.attach(&gDebug);
Runner.attach(&gDataBase);
Runner.addmsg("app is setup");
}
Observer中update一般為純虛,通過子類各自實現,這裡只是保證調用的介面一致,Listener中的attach、remove、notify一般建議不進行虛化,子類不用關心其內部的聚合內容,通過調用notify實現消息分發即可。當然也可以虛化,將這一系列的操作放到子類進行實現。
調用者應該註意在多線程環境中的使用環境,做好數據的同步工作。
應用場景
- 當一個對象改變需要通知到其他對象,而我們不確定由多少對象需要通知時;
- 當一個對象必須通知其他對象,而不需要知道對象是什麼實現時;
- 對於一堆對象,包含同樣的狀態或同樣的數據,通過同一個條件進行更新時。