设计模式(二):观察者模式
在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。
通俗点来说,就是一个主题类(subject)在状态发生改变时,通过观察者(observer)提供的方法,来更新观察者的状态。首先观察者需要到主题类中注册。
附带维基百科的代码:
python:相对简洁
class AbstractSubject(object): def register(self, listener): raise NotImplementedError("Must subclass me") def unregister(self, listener): raise NotImplementedError("Must subclass me") def notify_listeners(self, event): raise NotImplementedError("Must subclass me") class Listener(object): def __init__(self, name, subject): self.name = name subject.register(self) def notify(self, event): print self.name, "received event", event class Subject(AbstractSubject): def __init__(self): self.listeners = [] self.data = None def getUserAction(self): self.data = raw_input('Enter something to do:') return self.data # Implement abstract Class AbstractSubject def register(self, listener): self.listeners.append(listener) def unregister(self, listener): self.listeners.remove(listener) def notify_listeners(self, event): for listener in self.listeners: listener.notify(event) if __name__=="__main__": # make a subject object to spy on subject = Subject() # register two listeners to monitor it. listenerA = Listener("<listener A>", subject) listenerB = Listener("<listener B>", subject) # simulated event subject.notify_listeners ("<event 1>") # outputs: # <listener A> received event <event 1> # <listener B> received event <event 1> action = subject.getUserAction() subject.notify_listeners(action) #Enter something to do:hello # outputs: # <listener A> received event hello # <listener B> received event hello
C++代码,需要多理解:
#include <list> #include <vector> #include <algorithm> #include <iostream> using namespace std; // The Abstract Observer class ObserverBoardInterface { public: virtual void update(float a,float b,float c) = 0; }; // Abstract Interface for Displays class DisplayBoardInterface { public: virtual void show() = 0; }; // The Abstract Subject class WeatherDataInterface { public: virtual void registerob(ObserverBoardInterface* ob) = 0; virtual void removeob(ObserverBoardInterface* ob) = 0; virtual void notifyOb() = 0; }; // The Concrete Subject class ParaWeatherData: public WeatherDataInterface { public: void SensorDataChange(float a,float b,float c) { m_humidity = a; m_temperature = b; m_pressure = c; notifyOb(); } void registerob(ObserverBoardInterface* ob) { m_obs.push_back(ob); } void removeob(ObserverBoardInterface* ob) { m_obs.remove(ob); } protected: void notifyOb() { list<ObserverBoardInterface*>::iterator pos = m_obs.begin(); while (pos != m_obs.end()) { ((ObserverBoardInterface* )(*pos))->update(m_humidity,m_temperature,m_pressure); (dynamic_cast<DisplayBoardInterface*>(*pos))->show(); ++pos; } } private: float m_humidity; float m_temperature; float m_pressure; list<ObserverBoardInterface* > m_obs; }; // A Concrete Observer class CurrentConditionBoard : public ObserverBoardInterface, public DisplayBoardInterface { public: CurrentConditionBoard(WeatherDataInterface& a):m_data(a) { m_data.registerob(this); } void show() { cout<<"_____CurrentConditionBoard_____"<<endl; cout<<"humidity: "<<m_h<<endl; cout<<"temperature: "<<m_t<<endl; cout<<"pressure: "<<m_p<<endl; cout<<"_______________________________"<<endl; } void update(float h, float t, float p) { m_h = h; m_t = t; m_p = p; } private: float m_h; float m_t; float m_p; WeatherDataInterface& m_data; }; // A Concrete Observer class StatisticBoard : public ObserverBoardInterface, public DisplayBoardInterface { public: StatisticBoard(WeatherDataInterface& a):m_maxt(-1000),m_mint(1000),m_avet(0),m_count(0),m_data(a) { m_data.registerob(this); } void show() { cout<<"________StatisticBoard_________"<<endl; cout<<"lowest temperature: "<<m_mint<<endl; cout<<"highest temperature: "<<m_maxt<<endl; cout<<"average temperature: "<<m_avet<<endl; cout<<"_______________________________"<<endl; } void update(float h, float t, float p) { ++m_count; if (t>m_maxt) { m_maxt = t; } if (t<m_mint) { m_mint = t; } m_avet = (m_avet * (m_count-1) + t)/m_count; } private: float m_maxt; float m_mint; float m_avet; int m_count; WeatherDataInterface& m_data; }; int main(int argc, char *argv[]) { ParaWeatherData * wdata = new ParaWeatherData; CurrentConditionBoard* currentB = new CurrentConditionBoard(*wdata); StatisticBoard* statisticB = new StatisticBoard(*wdata); wdata->SensorDataChange(10.2, 28.2, 1001); wdata->SensorDataChange(12, 30.12, 1003); wdata->SensorDataChange(10.2, 26, 806); wdata->SensorDataChange(10.3, 35.9, 900); wdata->removeob(currentB); wdata->SensorDataChange(100, 40, 1900); delete statisticB; delete currentB; delete wdata; return 0; }