C++实现观察者(Observer)模式
2015-08-27 22:00
531 查看
观察者(Observer)模式,是常见的模式之一。比如一份报纸,有很多订户。订阅者并不知道报纸何时会送来,他只知道自己订了这份报纸。订阅者在这里担任着观察者的角色,而报社则是被观察者。
报纸一旦印刷完毕,就应该及时送到订户手中,如果将报社看作一个对象,则报纸便是观察者(订户)和被观察者(报社)之间的纽带。观察者需要维护一个与报纸相关的变量或函数,在这个具体问题中,这个变量就是订户是否收到报纸,可设置为一个布尔型,当收到时,订户需要更新这个变量。
1.订阅对象、解除订阅、通知更新的函数,是所有被观察者共有行为,所以将其抽象出来作为被观察者的接口。
2.发行函数模拟改变状态函数,因为不同的被观察者有不同的方式,所以将其声明为纯虚函数,在派生类中实现。
3.观察者用STD中的List模板来实现,所以需要析构函数来释放。
观察者接口说明:
1.由于所有观察者都有更新状态这一操作,所以将其声明为接口。
2.Update()函数对于不同的具体对象,有不同的行为,所以在派生类中实现,声明为纯虚函数。
3.ShowMessage()函数用来模拟与被观察者相关的操作,如果被观察者状态改变,观察者需要执行某种操作,则在这里实现。本例中用来显示收到报纸这一信息。
报纸一旦印刷完毕,就应该及时送到订户手中,如果将报社看作一个对象,则报纸便是观察者(订户)和被观察者(报社)之间的纽带。观察者需要维护一个与报纸相关的变量或函数,在这个具体问题中,这个变量就是订户是否收到报纸,可设置为一个布尔型,当收到时,订户需要更新这个变量。
#ifndef _OBSERVER_H_ #define _OBSERVER_H_ #include <list> using namespace std; class Observer; /* 被观察者接口 */ class Subject { public: Subject():m_Issue(0) { } void Attach(Observer *oo);//订阅此对象 void Detach(Observer *oo);//解除订阅 void Notify();//通知订阅者更新 void virtual Issue() = 0;//发行函数//纯虚幻数,虚基类 bool GetIssue() { return m_Issue; } ~Subject() { list<Observer*>::iterator iter1,iter2,temp; for (iter1 = m_observerList.begin(), iter2 = m_observerList.end(); iter1 != iter2;) { temp = iter1; ++iter1; m_observerList.erase(temp); } m_observerList.clear();//清理list } protected: bool m_Issue;//发行标志 list<Observer*> m_observerList;//订阅者队列 }; /*观察者接口*/ class Observer { public: Observer():m_receive(0){}; void virtual Update()//更新函数 { } void virtual ShowMessage() = 0;//模拟与被观察者相关的函数 protected: bool m_receive;//收到报纸标志 }; /* 具体的被观察者 */ class ConcreteSubject:public Subject { public: ConcreteSubject() {} void Issue(); }; /* 具体的观察者 */ class Subscriber1:public Observer { public: void virtual Update(); void ShowMessage(); }; class Subscriber2:public Observer { public: void virtual Update(); void ShowMessage(); }; #endif被观察者接口说明:
1.订阅对象、解除订阅、通知更新的函数,是所有被观察者共有行为,所以将其抽象出来作为被观察者的接口。
2.发行函数模拟改变状态函数,因为不同的被观察者有不同的方式,所以将其声明为纯虚函数,在派生类中实现。
3.观察者用STD中的List模板来实现,所以需要析构函数来释放。
观察者接口说明:
1.由于所有观察者都有更新状态这一操作,所以将其声明为接口。
2.Update()函数对于不同的具体对象,有不同的行为,所以在派生类中实现,声明为纯虚函数。
3.ShowMessage()函数用来模拟与被观察者相关的操作,如果被观察者状态改变,观察者需要执行某种操作,则在这里实现。本例中用来显示收到报纸这一信息。
#include "Observer.H" #include <algorithm> #include <iostream> /* 订阅报纸 */ void Subject::Attach(Observer *oo) { m_observerList.push_back(oo); } /* 取消订阅 */ void Subject::Detach(Observer *oo) { list<Observer*>::iterator iter; iter = std::find(m_observerList.begin(),m_observerList.end(),oo); //在list队列中查找是否有订阅者oo while(iter != m_observerList.end()) { m_observerList.erase(iter);//在list队列中删除掉查找到的订阅者oo break; } } /*通知更新*/ void Subject::Notify() { list<Observer*>::iterator iter=m_observerList.begin(); for ( ; iter != m_observerList.end(); iter++) { (*iter)->Update(); } } /* 更改状态 */ void ConcreteSubject::Issue() { this->m_Issue = !this->m_Issue;//发行标志取反 if ( this->m_Issue )//如果发行标志为true { cout << "Magazine is Issued\n"; this->Notify();// this->m_Issue = false; } } /*订阅者更新*/ void Subscriber1::Update() { this->m_receive = true; this->ShowMessage(); this->m_receive = false; } void Subscriber1::ShowMessage() { cout << "Subscriber1 has received the newspapers\n"; } /*订阅者更新*/ void Subscriber2::Update() { this->m_receive = true; this->ShowMessage(); this->m_receive = false; } void Subscriber2::ShowMessage() { cout << "Subscriber2 has received the newspapers\n"; }测试程序:
#include "Observer.H" #include <iostream> int main() { Subject *sub=new ConcreteSubject(); //被观察者 Observer *customer1 = new Subscriber1();//观察者1 Observer *customer2 = new Subscriber2();//观察者2 sub->Attach(customer1);//观察者1订阅报纸 sub->Attach(customer2);//观察者2订阅报纸 if (sub->GetIssue()) { cout << "Newspapers has issued\n"; } else { cout << "Newspapers has not issued\n"; } sub->Issue(); //发行报纸 cout<<endl; if (sub->GetIssue()) { cout << "Newspapers has issued\n"; } else { cout << "Newspapers has not issued\n"; } sub->Detach(customer1);//观察者1取消订阅 sub->Issue(); //发行报纸 return 0; }测试结果:
相关文章推荐
- (转)c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考
- C++ inline
- C语言中extern的用法
- C++(1)
- C语言(8)--合并数组
- C++ Primer 学习笔记与思考_9 表达式中过的那些容易忽略的地方
- 关于C++的面试题
- [C++]Remove Linked List Elements 删除链表中的元素
- [C++11 并发编程] 13 使用期望等待一次性事件
- [leetcode]Contains Duplicate C语言
- 快速排序>>>>C语言实现
- C++ string的size()和length()函数没有区别
- 黑马程序员——C语言中的scanf函数
- C语言一个细节地方的说明【防止使用不当而出错】
- C语言之指针
- c/c++左值和右值
- C/C++编程题之大数相乘
- c++—————————const
- c++函数的返回值
- 传递实参时 丢弃了类型限定