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 }

    输出结果:

  • 相关阅读:
    微信公众号内调用微信支付
    transform-translate3d
    Ubuntu16.04 install apache-flume-1.7.0-bin.tar.gz
    Ubuntu16.04 install apache-hive-2.X.X-bin.tar.gz
    Ubuntu16.04 install mysql5.X
    Ubuntu16.04 install hadoop-2.8.1.tar.gz伪分布式配置
    Ubuntu16.04 install jdk-8u144-linux-x64.tar.gz
    入门VMware Workstation下的Debian学习之Vim简单使用(三)
    入门VMware Workstation下的Debian学习之基本命令(二)
    Ubuntu16.04 install android-studio-ide-162.4069837-linux
  • 原文地址:https://www.cnblogs.com/SmallAndGreat/p/13551993.html
Copyright © 2011-2022 走看看