C++ 常用设计模式学习——观察者模式
观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe):定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都要得到通知并自动更新。
观察者模式从根本上讲必须包含两个角色:观察者和被观察对象。
-
-
观察者对象可以注册到被观察者的中,完成注册后可以检测被观察者的变化,接收被观察者的通知。当然观察者也可以被注销掉,停止对被观察者的监控。
Subject(目标)
目标知道它的观察者。可以有任意多个观察者观察同一个目标;
提供注册和删除观察者对象的接口。
Observer(观察者)
为那些在目标发生改变时需获得通知的对象定义一个更新接口。
ConcreteSubject(具体目标)
将有关状态存入各ConcreteObserver对象;
当它的状态发生改变时,向它的各个观察者发出通知。
ConcreteObserver(具体观察者)
维护一个指向ConcreteSubject对象的引用;
存储有关状态,这些状态应与目标的状态保持一致;
实现Observer的更新接口以使自身状态与目标的状态保持一致。
观察者模式按照以下方式进行协作:
1)当ConcreteSubject发生任何可能导致其观察者与其本身状态不一致的改变时,它将通知它的各个观察者;
2)在得到一个具体目标的改变通知后,ConcreteObserver对象可向目标对象查询信息。ConcreteObserver使用这些信息以使它的状态与目标对象的状态一致。
适用场合:
1)当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立的改变和复用;
2)当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变;
3)当一个对象必须通知其它对象,而它又不能假定其它对象是谁;也就是说,你不希望这些对象是紧密耦合的。
/* * 关键代码:在目标类中增加一个ArrayList来存放观察者们。 */ #include <iostream> #include <list> #include <memory> using namespace std; class View; //被观察者抽象类 数据模型 class DataModel { public: virtual ~DataModel(){} virtual void addView(View* view) = 0; virtual void removeView(View* view) = 0; virtual void notify() = 0; //通知函数 }; //观察者抽象类 视图 class View { public: virtual ~View(){ cout << "~View()" << endl; } virtual void update() = 0; virtual void setViewName(const string& name) = 0; virtual const string& name() = 0; }; //具体的被观察类, 整数模型 class IntDataModel:public DataModel { public: ~IntDataModel() { m_pViewList.clear(); } virtual void addView(View* view) override { shared_ptr<View> temp(view); auto iter = find(m_pViewList.begin(), m_pViewList.end(), temp); if(iter == m_pViewList.end()) { m_pViewList.push_front(temp); } else { cout << "View already exists" << endl; } } void removeView(View* view) override { auto iter = m_pViewList.begin(); for(; iter != m_pViewList.end(); iter++) { if((*iter).get() == view) { m_pViewList.erase(iter); cout << "remove view" << endl; return; } } } virtual void notify() override { auto iter = m_pViewList.begin(); for(; iter != m_pViewList.end(); iter++) { (*iter).get()->update(); } } private: list<shared_ptr<View>> m_pViewList; }; //具体的观察者类 表视图 class TableView : public View { public: TableView() : m_name("unknow"){} TableView(const string& name) : m_name(name){} ~TableView(){ cout << "~TableView(): " << m_name.data() << endl; } void setViewName(const string& name) { m_name = name; } const string& name() { return m_name; } void update() override { cout << m_name.data() << " update" << endl; } private: string m_name; }; int main() { /* * 这里需要补充说明的是在此示例代码中,View一旦被注册到DataModel类之后,DataModel解析时会自动解析掉 * 内部容器中存储的View对象,因此注册后的View对象不需要在手动去delete,再去delete View对象会出错。 */ View* v1 = new TableView("TableView1"); View* v2 = new TableView("TableView2"); View* v3 = new TableView("TableView3"); View* v4 = new TableView("TableView4"); IntDataModel* model = new IntDataModel; model->addView(v1); model->addView(v2); model->addView(v3); model->addView(v4); model->notify(); cout << "-------------\n" << endl; model->removeView(v1); model->notify(); delete model; model = nullptr; return 0; }
本文来自博客园,作者:Jcpeng_std,转载请注明原文链接:https://www.cnblogs.com/JCpeng/p/15116554.html