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 }

输出结果:

原文地址:https://www.cnblogs.com/SmallAndGreat/p/13551993.html