觀察者模式:定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一主題對象,在主題對象的狀態發生變化時,會通知所有的觀察者。
觀察者模式角色如下:
抽象主題(Subject)角色:抽象主題角色提供維護一個觀察者對象集合的操作方法,對集合的增加、刪除等。
具體主題(ConcreteSubject)角色:將有關狀態存入具體的觀察者對象;在具體主題的內部狀態改變時,給所有登記過的觀察者發通知。具體主題角色負責實現抽象主題中的方法。
抽象觀察者(Observer)角色:為具體觀察者提供一個更新接口。
具體觀察者(ConcreteObserver)角色:存儲與主題相關的自洽狀態,實現抽象觀察者提供的更新接口。
Case:
在教室里老師還沒有來,同學都在干着各的事情,小張正在打游戲,小李正在抄作業....., 現在同學們要求班長當卧底,監視老師,當老師來了通知大家一聲。然后打游戲的馬上停止,抄作業的也停止。
這里班長相當於是一個通知者, 小張、小李,以及其他同學顯然是監聽者,他們監聽了班長那的消息,一旦老師來了馬上采取相關的行動。
首先,先把通知者的行為抽象為一個接口:(subject)
class INotifier { public: virtual void registerListenner(ITeacherListenner *l) =0 ; virtual void removeListenner(ITeacherListenner *l) =0 ; virtual void notify() =0 ; };
第二,然后班長作為一個具體的通知者:(ConcreteSubject)
class MonitorNotifier:public INotifier { public: void registerListenner(ITeacherListenner *l) { listenners.push_back(l); }
void removeListenner(ITeacherListenner *l) { list<ITeacherListenner*>::iterator it; for(it=listenners.begin();it!=listenners.end();it++) { if(*it == l) { listenners.remove(l); break; } } }
void notify() { list<ITeacherListenner*>::iterator it; for(it=listenners.begin();it!=listenners.end();it++) { (*it)->onTecherComming(mValue;);
}
}
void setValue(int value)
{
mValue = value;
notify();
}
private:
list<ITeacherListenner*> listenners;
int mValue;
};
第三, 定義一個監聽者的接口,想要監聽老師來了這個消息的同學必須要實現這個接口:
class ITeacherListenner { public: virtual void onTecherComming(int value) = 0;
};
第四,ZhangSan 和 LiSi 監聽了老師來了這個接口:
class ZhangSan:public ITeacherListenner { public: void onTecherComming(int value) { stopCopyWork(value); } void stopCopyWork(int value) { cout<<"zhangsan stopCopyWork + "<<value<<endl; } }; class LiSi:public ITeacherListenner { public: void onTecherComming(int value) { stopPlayGame(value); } void stopPlayGame(int value) { cout<<"lisi stopPlayGame + "<<value<<endl; } };
int main() { cout << "Hello World1-------------"<<endl; MonitorNotifier monitor; ZhangSan zs; LiSi ls; monitor.registerListenner(&zs); monitor.registerListenner(&ls); monitor.setValue(1); cout << "Hello World2-------------"<<endl; monitor.removeListenner(&ls); monitor.setValue(2); return 0; }
運行結果如下:
Hello World1-------------
zhangsan stopCopyWork + 1
lisi stopPlayGame + 1
Hello World2-------------
zhangsan stopCopyWork + 2
最后:完整的Demo(下載后刪掉.sh)