观察者模式?我觉得用通知者模式来形容也是可以的。
某个事物(Subject)的某些状态发生变化,于是通知观察列表中的观察者(Observer)去更新(Update)自身的相应状态,而这个相应的状态,是和Subject息息相关的。
《Head First 设计模式》设计原则
设计原则一
找出程序中会变化的方面,然后将其和固定不变的方面相分离——
观察者模式中,会变化的是主题的状态,以及观察者的数目和类型。使用这个模式,可以改变依赖于主题状态的对象,而不必改变主题
设计原则二
针对接口编程,不针对实现编程——
主题和观察者都是用接口:观察者利用主体的接口向主体注册,而主题利用观察者的接口Update通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点。
设计原则三
多用组合,少用继承——
观察者模式利用“组合”将许多观察者组合进主题中。对象之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式而产生的。
实际场景:
某些屌丝男(观察者)一直关注着Iphone5S的价格,屌丝男(观察者)的记住了当前的价格为price = 6000,由于这个价格太高,所以屌丝男(观察者)请求关注这个产品价格的变动,于是京东商城(通知者)将屌丝男(观察者)添加入了被通知列表,于是当某一次京东开展降价活动,Iphone5S的价格发生了变化,京东商城(通知者)循环遍历屌丝男(观察者)列表,告诉他们:屌丝男(观察者),你们的春天来了,Iphone5S降价了,你们快执行更新函数Update来做出相应的策略选择吧!于是屌丝男(观察者)们纷纷调用各自的Update函数,去更新Price(屌丝男自身的数据一直是price
= 6000,现在通过执行get操作,更新这个price),然后再根据Price的情况做出其他的决策。
OK,大致就是这个原理。
这里看过一篇点击打开CSDN博客链接,写得不错。
好了,啥也不说了,上代码
【观察者基类】
class Observer{ public: Observer(void); virtual ~Observer(void); virtual void Update(void) = 0; Subject* subject; }; //观察者基类 Observer::Observer(void){ } Observer::~Observer(void){ }
【DiaosinanObserver类】
class DiaosinanObserver : public Observer{ public: DiaosinanObserver(void); ~DiaosinanObserver(void); void Update(void); public: double price; }; //观察者 DiaosinanObserver::DiaosinanObserver(void){ } DiaosinanObserver::~DiaosinanObserver(void){ } void DiaosinanObserver::Update(void){ price = ((JDSubject*)this->subject)->getPrice(); std::cout << "====屌丝男们做出如下反应====\n"; if (price < 4000) { std::cout << "====价格很合理,我买了====\n"; this->subject->Detach(this); }else{ std::cout <<"====价格仍旧太高,屌丝伤不起====\n"; } }
【通知者基类】
class Subject{ public: Subject(void); virtual ~Subject(void); virtual void Attach(Observer* observer); virtual void Detach(Observer* observer); void Notify(void); public: std::list<Observer*> lObserver; }; //通知者基类 Subject::Subject(void){ } Subject::~Subject(void){ } void Subject::Attach(Observer *observer){ this->lObserver.push_back(observer); observer->subject = this; } void Subject::Detach(Observer *observer){ this->lObserver.remove(observer); observer->subject = NULL; } void Subject::Notify(void){ for (std::list<Observer*>::iterator p = this->lObserver.begin(); p != this->lObserver.end(); ++p) { (*p)->Update(); } }
【通知者子类】
class JDSubject : public Subject{ public: JDSubject(void); ~JDSubject(void); void setPrice(double pri){price = pri;} double getPrice(void){return price;} protected: double price; }; //通知者子类 JDSubject::JDSubject(void){ } JDSubject::~JDSubject(void){ }
【main】
int main(int argc, const char * argv[]) { DiaosinanObserver* diaosinan = new DiaosinanObserver(); diaosinan->price = 6000; JDSubject* jd = new JDSubject(); jd->setPrice(6000); std::cout << "====太贵了,屌丝男要求关注Price====\n"; //太贵了,屌丝男要求关注Price jd->Attach(diaosinan); std::cout << "====价格变化,通知屌丝男们====\n"; //价格变化,通知屌丝男们 jd->setPrice(5000); jd->Notify(); std::cout << "====观察者列表中的成员个数为:" << jd->lObserver.size() << std::endl; std::cout << "====价格再次变化,继续通知屌丝男们====\n"; //价格再次变化,继续通知屌丝男们 jd->setPrice(3000); jd->Notify(); std::cout << "====观察者列表中的成员个数为:" << jd->lObserver.size() << std::endl; delete diaosinan; diaosinan = NULL; delete jd; jd = NULL; return 0; }
【结果】
====太贵了,屌丝男要求关注Price====
====价格变化,通知屌丝男们====
====屌丝男们做出如下反应====
====价格仍旧太高,屌丝伤不起====
====观察者列表中的成员个数为:1
====价格再次变化,继续通知屌丝男们====
====屌丝男们做出如下反应====
====价格很合理,我买了====
====观察者列表中的成员个数为:0