010 --- 第14章 观察者模式

简述:

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

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

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

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

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

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

 

应用场景:需要一个标志相应所有状态的改变,主题类封装了观察者列表,主题类改变状态通知观察者,所有观察者改变自身的状态

 

注:开发环境调整为VS2017,操作系统win11

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

 

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

 

输出结果:

 

 

 

 

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

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

代码如下:

  1 #include <iostream>
  2 #include <list>
  3 #include <string>
  4 using namespace std;
  5 
  6 //class CSecretary;
  7 class CSubject;
  8 // 抽象观察者类
  9 class CObserver
 10 {
 11 protected:
 12     string m_szName;
 13     //CSecretary* m_pSecretary;
 14     CSubject* m_pSubject;
 15 
 16 public:
 17     //CObserver(string szName, CSecretary* pSecretary);
 18     CObserver(string szName, CSubject* pSubject) : m_szName(szName), m_pSubject(pSubject) {};
 19     virtual ~CObserver() {};
 20     virtual void UpDate() {};
 21 };
 22 
 23 //// 秘书类(双向耦合代码)
 24 //class CSecretary
 25 //{
 26 //private:
 27 //    list<CObserver*> m_listCObserver;
 28 //    string m_szAction;
 29 //
 30 //public:
 31 //    CSecretary() {}
 32 //
 33 //    virtual ~CSecretary()
 34 //    {
 35 //        if (!m_listCObserver.empty())
 36 //        {
 37 //            m_listCObserver.clear();
 38 //        }
 39 //    }
 40 //
 41 //    virtual void Attach(CObserver* pObserver)
 42 //    {
 43 //        m_listCObserver.push_back(pObserver);
 44 //    }
 45 //
 46 //    virtual void Detach(CObserver* pDelObserver)
 47 //    {
 48 //        if (!m_listCObserver.empty())
 49 //        {
 50 //            m_listCObserver.remove(pDelObserver);
 51 //        }
 52 //    }
 53 //
 54 //    virtual void Notify()
 55 //    {
 56 //        for (CObserver* pObserver : m_listCObserver)
 57 //        {
 58 //            pObserver->UpDate();
 59 //        }
 60 //    }
 61 //
 62 //    void SetSecretaryAction(string szAction)
 63 //    {
 64 //        m_szAction = szAction;
 65 //    }
 66 //
 67 //    string GetSecretaryAction()
 68 //    {
 69 //        return m_szAction;
 70 //    }
 71 //};
 72 
 73 // 抽象主题类
 74 class CSubject
 75 {
 76 private:
 77     list<CObserver*> m_listCObserver;
 78     string m_szAction;
 79 
 80 public:
 81     CSubject() {};
 82     virtual ~CSubject()
 83     {
 84         if (!m_listCObserver.empty())
 85         {
 86             m_listCObserver.clear();
 87         }
 88     }
 89 
 90     virtual void Attach(CObserver* pObserver)
 91     {
 92         m_listCObserver.push_back(pObserver);
 93     }
 94 
 95     virtual void Detach(CObserver* pDelObserver)
 96     {
 97         if (!m_listCObserver.empty())
 98         {
 99             m_listCObserver.remove(pDelObserver);
100         }
101     }
102 
103     virtual void Notify()
104     {
105         for (CObserver* pObserver : m_listCObserver)
106         {
107             pObserver->UpDate();
108         }
109     }
110 
111     void SetSubjectState(string szAction)
112     {
113         m_szAction = szAction;
114     }
115 
116     string GetSubjectState()
117     {
118         return m_szAction;
119     }
120 };
121 
122 // 看股票的同事(具体观察者类)
123 class CStockObserver : public CObserver
124 {
125 public:
126     //CStockObserver(string szName, CSecretary* pSecretary)
127     //    : CObserver(szName, pSecretary)
128     //{
129     //
130     //}
131 
132     CStockObserver(string szName, CSubject* pSubject)
133         : CObserver(szName, pSubject) {}
134 
135     virtual ~CStockObserver() {}
136 
137     virtual void UpDate()
138     {
139         //cout << "[" << m_pSecretary->GetSecretaryAction() << "]"
140         //    << "[" << m_szName << "]" << "关闭股票行情,继续工作" << endl;
141 
142         cout << "[" << m_pSubject->GetSubjectState() << "]"
143             << "[" << m_szName << "]" << "关闭股票行情,继续工作。。。" << endl;
144     }
145 };
146 
147 // 看NBA的同事(具体观察者类)
148 class CNBAObserver : public CObserver
149 {
150 public:
151     //CNBAObserver(string szName, CSecretary* pSecretary)
152     //    : CObserver(szName, pSecretary) {}
153 
154     CNBAObserver(string szName, CSubject* pSubject)
155         : CObserver(szName, pSubject) {}
156 
157     virtual ~CNBAObserver() {}
158 
159     virtual void UpDate()
160     {
161         //cout << "[" << m_pSecretary->GetSecretaryAction() << "]"
162         //    << "[" << m_szName << "]" << "关闭NBA直播,继续工作" << endl;
163 
164         cout << "[" << m_pSubject->GetSubjectState() << "]"
165             << "[" << m_szName << "]" << "关闭NBA直播,继续工作。。。" << endl;
166     }
167 };
168 
169 // 我嫌麻烦,把具体主题类的共有内容放到抽象主题类里写了,懒得写两遍
170 // 老板(具体主题类)
171 class CBoss : public CSubject
172 {
173 };
174 
175 // 秘书(具体主题类)
176 class CReception : public CSubject
177 {
178 };
179 
180 // C++资源回收,记住哪里创建就要哪里释放
181 // 其他作用域只是指针传递,如果在别的地方释放,容易导致多次释放报错
182 int main()
183 {
184     //CSecretary Secretary;
185     CBoss Boss;
186 
187     //CStockObserver StockObserver("GHL", &Secretary);
188     //CNBAObserver NBAObserver("GGG", &Secretary);
189     CStockObserver StockObserver("GHL", &Boss);
190     CNBAObserver NBAObserver("GGG", &Boss);
191 
192     //Secretary.Attach(&StockObserver);
193     //Secretary.Attach(&NBAObserver);
194 
195     Boss.Attach(&StockObserver);
196     Boss.Attach(&NBAObserver);
197 
198     //Secretary.SetSecretaryAction("老板回来了!");
199     Boss.SetSubjectState("我胡汉三回来了!");
200 
201     //Secretary.Notify();
202     Boss.Notify();
203 
204 
205     cout << "\n华丽的分割线\n" << endl;
206     CReception Reception;
207 
208     CStockObserver StockObserve1("123", &Reception);
209     CNBAObserver NBAObserve1("456", &Reception);
210 
211     Reception.Attach(&StockObserve1);
212     Reception.Attach(&NBAObserve1);
213     Reception.Detach(&NBAObserve1);
214 
215     Reception.SetSubjectState("老板回来了!");
216 
217     Reception.Notify();
218 
219     system("pause");
220     return 0;
221 }

输出结果:

 

posted @ 2020-08-24 09:16  二是一种不三不亖的范  阅读(128)  评论(0编辑  收藏  举报