zoukankan      html  css  js  c++  java
  • 窥探观察者模式

      观察者模式(obsever pattern)又名发行/订阅模式(publish-subscribe pattern),是事件驱动模型的简化版本,也是我们熟知的MVC架构的核心部分。

     

    下面以博客园订阅博客为例,窥探一下观察者模式蕴含的奥秘:

      当博主发表新文章的时候,即博主状态发生了改变,那些订阅的读者就会收到通知,然后进行相应的动作,比如去看文章,或者收藏起来。博主与读者之间存在种一对多的依赖关系。

    【对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新】这就是观察者模式,所谓的观察者可以理解为关注博客的读者被观察的对象(Subject)即为博主,博主自身状态发生改变时会发出通知(Notify),读者(Obsever)可以通过更新操作(Update)获得博主的最新消息。

     

      观察者模式的实现有以下4类角色:

    • 抽象主题(Subject:可以用博客的抽象基类来理解,一般用一个抽象类或者一个接口实现。Subject提供依赖于它的观察者 Observer 的注册( Attach) 和注销( Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作( Notify)。
    • 抽象观察者(Observer:可以用观察者的抽象基类来理解,抽象观察者一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。
    • 具体主题(ConcreteSubject:就是你所关注的具体博主(如果你关注了我这个类就是acelit-cnblog),继承自抽象博客,ConcreteSubject将有关状态存入具体现察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
    • 具体观察者(ConcreteObserver:也就是关注博客的读者,继承自抽象观察者,ConcreteObserver存储与主题的状态自恰的状态。具体观察者实现抽象观察者所要求的更新接口,以便使本身的状态与主题的状态相协调。    

     

      这么说大家可能还不太理解,结合下面这张图和实现代码来分析:

      

    观察者模型所需4大类(obsever.h):

     1 #include <iostream>
     2 #include <string>
     3 #include <list>
     4 #include <iterator>
     5 using namespace std;
     6 //观察者  
     7 class Observer
     8 {
     9 public:
    10     Observer() {}
    11     virtual ~Observer() {}
    12     virtual void Update() {}
    13 };
    14 //博客  
    15 class Blog
    16 {
    17 public:
    18     Blog() {}
    19     virtual ~Blog() {}
    20     void Attach(Observer *observer) { m_observers.push_back(observer); }     //添加观察者  
    21     void Remove(Observer *observer) { m_observers.remove(observer); }        //移除观察者  
    22     void Notify() //通知观察者  
    23     {
    24         list<Observer*>::iterator iter = m_observers.begin();
    25         for (; iter != m_observers.end(); iter++)
    26             (*iter)->Update();
    27     }
    28     virtual void SetStatus(string s) { m_status = s; } //设置状态  
    29     virtual string GetStatus() { return m_status; }    //获得状态  
    30 private:
    31     list<Observer* > m_observers; //观察者链表  
    32 protected:
    33     string m_status; //状态  
    34 };
    35 
    36 //具体博客类  
    37 class CNBlog : public Blog
    38 {
    39 private:
    40     string m_name; //博主名称  
    41 public:
    42     CNBlog(string name) : m_name(name) {}
    43     ~CNBlog() {}
    44     void SetStatus(string s) { m_status = "cnblog通知 : " + m_name + s; } //具体设置状态信息  
    45     string GetStatus() { return m_status; }
    46 };
    47 //具体观察者  
    48 class ObserverBlog : public Observer
    49 {
    50 private:
    51     string m_name;  //观察者名称  
    52     list<Blog* > m_blog;   //订阅者链表
    53 public:
    54     ObserverBlog(string name) : m_name(name){}
    55     ~ObserverBlog() {}
    56     void Attach(Blog *blog) { m_blog.push_back(blog); }     //添加订阅者  
    57     void Remove(Blog *blog) { m_blog.remove(blog); }        //移除订阅者    
    58     void Update()  //获得更新状态  
    59     {
    60 //为了防止订阅者重复输出所观察的博客,每次只输出最后一个博主的更新消息
    61         list<Blog*>::iterator iter = m_blog.end();
    62         string status = (*(--iter))->GetStatus();
    63         if (status != "")
    64             cout << m_name << "-------" << status << endl;
    65     }
    66 };

    测试代码:

     1 //测试代码
     2 //3个观察者,3个订阅者,第1个观测者订阅了1、2、3号订阅者,第1个订阅者被1、2、3号观察者关注。
     3 #include "obsever.h"
     4 
     5 int main()
     6 {
     7     Blog *blog1 = new CNBlog("acelit1");
     8     Blog *blog2 = new CNBlog("acelit2");
     9     Blog *blog3 = new CNBlog("acelit3");
    10 
    11     ObserverBlog *observer1 = new ObserverBlog("subscriber1");
    12     ObserverBlog *observer2 = new ObserverBlog("subscriber2");
    13     ObserverBlog *observer3 = new ObserverBlog("subscriber3");
    14 
    15     observer1->Attach(blog1);
    16     observer2->Attach(blog1);
    17     observer3->Attach(blog1);
    18 
    19     blog1->Attach(observer1);
    20     blog1->Attach(observer2);
    21     blog1->Attach(observer3);
    22     blog1->SetStatus("发表设计模式C++实现——观察者模式");
    23     blog1->Notify();
    24 
    25     observer1->Attach(blog2);
    26     blog2->Attach(observer1);
    27     blog2->SetStatus(" published: observer pattern");
    28     blog2->Notify();
    29 
    30     observer1->Attach(blog3);
    31     blog3->Attach(observer1);
    32     blog3->SetStatus(" published: 观察者模式");
    33     blog3->Notify();
    34 
    35     delete blog1; 
    36     delete blog2;
    37     delete blog3;
    38     delete observer1;
    39     delete observer2;
    40     delete observer3;
    41 
    42     system("pause");
    43     return 0;
    44 }

    测试结果:

    博主acelit1状态改变,observer1~3均更新状态;博主acelit2和acelit3状态改变,只有observer1更新状态。

     全文完。欢迎各位老司机批评指正O(∩_∩)O

     

  • 相关阅读:
    管理中的“变”与“不变”
    软件项目需求分析与管理的十大疑问
    小商家也要有O2O思维
    互联网时代CIO生存法则
    浅谈项目经理与部门经理之间的关系
    沃尔玛:“最后一公里”的致命伤
    大数据分析案例:永远别忘记天气这个变量
    IT项目中的6类知识转移
    C
    linu入门
  • 原文地址:https://www.cnblogs.com/always-chang/p/6195198.html
Copyright © 2011-2022 走看看