zoukankan      html  css  js  c++  java
  • 010 --- 第14章 观察者模式

    简述:

      观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够主动更新自己。

      观察者模式包括:抽象主题类、具体主题类、抽象观察者类、具体观察者类。

        抽象主题类:它把所有对观察者对象的指针保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

        具体主题类:具体主题,将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有登记过的观察者发出通知。

        抽象观察者类:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。

        具体观察者类:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。

    观察者模式代码:C++与C#的区别要注意相互包含的问题,同时要注意声明顺序。

      1 #include <iostream>
      2 #include <list>
      3 using namespace std;
      4 
      5 // 抽象观察者类
      6 class CObserver
      7 {
      8 public:
      9     virtual void UpDate() {}
     10 };
     11 
     12 // 抽象通知者类
     13 class CSubject
     14 {
     15 private:
     16     list<CObserver*> m_listObserver;
     17 
     18 public:
     19     virtual void Attach(CObserver* pObserver)
     20     {
     21         m_listObserver.push_back(pObserver);
     22     }
     23 
     24     virtual void Detach(CObserver* pObserver)
     25     {
     26         m_listObserver.remove(pObserver);
     27     }
     28 
     29     virtual void Notify()
     30     {
     31         for (CObserver* pObserver : m_listObserver)
     32             pObserver->UpDate();
     33     }
     34 };
     35 
     36 // 具体通知者类
     37 class CConcreteSubject : public CSubject
     38 {
     39 private:
     40     string m_szSubjectState;
     41 
     42 public:
     43     void SetSubjectState(string szSubjectState)
     44     {
     45         m_szSubjectState = szSubjectState;
     46     }
     47 
     48     string GetSubjectState()
     49     {
     50         return m_szSubjectState;
     51     }
     52 };
     53 
     54 // 具体观察者类
     55 class CConcreteObserver : public CObserver
     56 {
     57 private:
     58     string m_szName;
     59     CConcreteSubject* m_pSubject;
     60 
     61 public:
     62     CConcreteObserver(CConcreteSubject* pSubject, string szName)
     63     {
     64         m_szName = szName;
     65         m_pSubject = pSubject;
     66     }
     67 
     68     virtual void UpDate()
     69     {
     70         cout << "观察者[" << m_szName << "]的新状态是[" 
     71             << m_pSubject->GetSubjectState() << "]" << endl;
     72     }
     73 
     74     void SetSubject(CConcreteSubject* pSubject)
     75     {
     76         m_pSubject = pSubject;
     77     }
     78 
     79     CSubject* GetSubject()
     80     {
     81         return m_pSubject;
     82     }
     83 };
     84 
     85 int main()
     86 {
     87     CConcreteSubject ConcreteSubject;
     88     CConcreteObserver ConcreteObserver1(&ConcreteSubject, "X");
     89     CConcreteObserver ConcreteObserver2(&ConcreteSubject, "Y");
     90     CConcreteObserver ConcreteObserver3(&ConcreteSubject, "Z");
     91 
     92     ConcreteSubject.Attach(&ConcreteObserver1);
     93     ConcreteSubject.Attach(&ConcreteObserver2);
     94     ConcreteSubject.Attach(&ConcreteObserver3);
     95 
     96     ConcreteSubject.Detach(&ConcreteObserver2);
     97 
     98     ConcreteSubject.SetSubjectState("ABC");
     99 
    100     ConcreteSubject.Notify();
    101 
    102     system("pause");
    103     return 0;
    104 }

    输出结果:

     注:C++是没有C#中的委托事件这种语法的,但是可以用函数指针来实现,笔者比较懒,没写。

    例:前台监测老板是否回来了。

    代码如下:

      1 #include <iostream>
      2 #include <list>
      3 using namespace std;
      4 
      5 class CSubject;
      6 // 抽象观察者类
      7 class CObserver
      8 {
      9 protected:
     10     string m_szName;
     11     CSubject* m_pSubject;
     12 
     13 public:
     14     CObserver(string szName, CSubject* pSubject) : m_szName(szName), m_pSubject(pSubject) {};
     15     virtual ~CObserver() {};
     16     virtual void UpDate() {};
     17 };
     18 
     19 // 抽象主题类
     20 class CSubject
     21 {
     22 private:
     23     list<CObserver*> m_listCObserver;
     24     string m_szAction;
     25 
     26 public:
     27     CSubject() {};
     28     virtual ~CSubject()
     29     {
     30         if (!m_listCObserver.empty())
     31         {
     32             m_listCObserver.clear();
     33         }
     34     }
     35 
     36     virtual void Attach(CObserver* pObserver)
     37     {
     38         m_listCObserver.push_back(pObserver);
     39     }
     40 
     41     virtual void Detach(CObserver* pDelObserver)
     42     {
     43         if (!m_listCObserver.empty())
     44         {
     45             m_listCObserver.remove(pDelObserver);
     46         }
     47     }
     48 
     49     virtual void Notify()
     50     {
     51         for (CObserver* pObserver : m_listCObserver)
     52         {
     53             pObserver->UpDate();
     54         }
     55     }
     56 
     57     void SetSubjectState(string szAction)
     58     {
     59         m_szAction = szAction;
     60     }
     61 
     62     string GetSubjectState()
     63     {
     64         return m_szAction;
     65     }
     66 };
     67 
     68 // 看股票的同事(具体观察者类)
     69 class CStockObserver : public CObserver
     70 {
     71 public:
     72     CStockObserver(string szName, CSubject* pSubject)
     73         : CObserver(szName, pSubject) {}
     74 
     75     virtual ~CStockObserver() {}
     76 
     77     virtual void UpDate()
     78     {
     79         cout << "[" << m_pSubject->GetSubjectState() << "]"
     80             << "[" << m_szName << "]" << "关闭股票行情,继续工作。。。" << endl;
     81     }
     82 };
     83 
     84 // 看NBA的同事(具体观察者类)
     85 class CNBAObserver : public CObserver
     86 {
     87 public:
     88     CNBAObserver(string szName, CSubject* pSubject)
     89         : CObserver(szName, pSubject) {}
     90 
     91     virtual ~CNBAObserver() {}
     92 
     93     virtual void UpDate()
     94     {
     95         cout << "[" << m_pSubject->GetSubjectState() << "]"
     96             << "[" << m_szName << "]" << "关闭NBA直播,继续工作。。。" << endl;
     97     }
     98 };
     99 
    100 // 我嫌麻烦,把具体主题类的共有内容放到抽象主题类里写了,懒得写两遍
    101 // 老板(具体主题类)
    102 class CBoss : public CSubject
    103 {
    104 };
    105 
    106 // 秘书(具体主题类)
    107 class CReception : public CSubject
    108 {
    109 };
    110 
    111 // C++资源回收,记住哪里创建就要哪里释放
    112 // 其他作用域只是指针传递,如果在别的地方释放,容易导致多次释放报错
    113 int main()
    114 {
    115     CBoss Boss;
    116 
    117     CStockObserver StockObserver("GHL", &Boss);
    118     CNBAObserver NBAObserver("GGG", &Boss);
    119 
    120     Boss.Attach(&StockObserver);
    121     Boss.Attach(&NBAObserver);
    122 
    123     Boss.SetSubjectState("我胡汉三回来了!");
    124 
    125     Boss.Notify();
    126 
    127 
    128     cout << "
    华丽的分割线
    " << endl;
    129     CReception Reception;
    130 
    131     CStockObserver StockObserve1("123", &Reception);
    132     CNBAObserver NBAObserve1("456", &Reception);
    133 
    134     Reception.Attach(&StockObserve1);
    135     Reception.Attach(&NBAObserve1);
    136     Reception.Detach(&NBAObserve1);
    137 
    138     Reception.SetSubjectState("老板回来了!");
    139 
    140     Reception.Notify();
    141 
    142     system("pause");
    143     return 0;
    144 }

    输出结果:

  • 相关阅读:
    移动开发 Native APP、Hybrid APP和Web APP介绍
    urllib与urllib2的学习总结(python2.7.X)
    fiddler及postman讲解
    接口测试基础
    UiAutomator2.0 和1.x 的区别
    adb shell am instrument 命令详解
    GT问题记录
    HDU 2492 Ping pong (树状数组)
    CF 567C Geometric Progression
    CF 545E Paths and Trees
  • 原文地址:https://www.cnblogs.com/SmallAndGreat/p/13551993.html
Copyright © 2011-2022 走看看