观察者模式(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
原文链接: https://www.cnblogs.com/always-chang/p/6195198.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/246039
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!