文章目录

* 模式的定义与特点 <https://blog.csdn.net/zyzmzm_/article/details/89464024#_8>
* 模式的结构与实现 <https://blog.csdn.net/zyzmzm_/article/details/89464024#_21>
* 角色 <https://blog.csdn.net/zyzmzm_/article/details/89464024#_22>
* 实现方式 <https://blog.csdn.net/zyzmzm_/article/details/89464024#_28>
* 结构程序示例 <https://blog.csdn.net/zyzmzm_/article/details/89464024#_36>
* 具体应用程序示例 <https://blog.csdn.net/zyzmzm_/article/details/89464024#_167>


观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。

在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系
,可以根据需要增加和删除观察者,使得系统更易于扩展。

<>模式的定义与特点

观察者模式定义如下:


观察者模式(Observer
Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

观察者模式(Observer)完美的将观察者和被观察的对象分离开
。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。

面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面
。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。

观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。

观察者模式包含观察目标和观察者两类对象
,一个目标可以有任意数目的与之相依赖的观察者,一旦观察目标的状态发生改变,所有的观察者都将得到通知。作为对这个通知的响应,每个观察者都将监视观察目标的状态以使其状态与目标状态同步,这种交互也称为
发布-订阅(Publish-Subscribe)。观察目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅它并接收通知。

<>模式的结构与实现

<>角色

在观察者模式结构图中包含如下几个角色:

* Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来
增加和删除观察者对象,同时它定义了通知方法Notify()。目标类可以是接口,也可以是抽象类或具体类。
* ConcreteSubject(具体目标):具体目标是目标类的派生类
,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
* Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。
* ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态
,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法
。通常在实现时,可以调用具体目标类的attach()方法将自己添加到目标类的集合中或通过detach()方法将自己从目标类的集合中删除。
<>实现方式

观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。在上面的例子中,业务数据是被观察对象,用户界面是观察者。

观察者和被观察者之间存在“观察”的逻辑关联,当被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应
。如果在用户界面、业务数据之间使用这样的观察过程,可以确保界面和数据之间划清界限,假定应用程序的需求发生变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。

注意:
实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用
,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。
无论是观察者“观察”观察对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。

<>结构程序示例

下面通过示意代码来对该模式进行进一步分析。
/** * Copyright: Copyright(c) 2019 * Created on 26/4/2019 * Author : ZYZMZM *
Version 1.0 * Title : Observer Pattern **/ #include <iostream> #include <list>
using namespace std; /* 抽象观察者,提供update接口 */ class AbstractObserver { public:
virtualvoid update() = 0; }; class Object; /* 具体观察者,实现update方法 */ class observer
: public AbstractObserver { public: /* 构造具体观察者,也可以单独写 */ observer(string str,
Object* obj) :name(str), ob(obj) {} void update(); string getName() { return
name; } private: string name; Object* ob; }; /* 抽象目标,提供抽象接口 */ class
AbstractObject{ public: /* 添加观察者 */ virtual void Add(observer* ob) = 0; /*
删除观察者 */ virtual void Remove(observer* ob) = 0; /* 通知所有观察者 */ virtual void
Notify() = 0; }; /* 具体目标,实现抽象目标所提供的接口 */ class Object : public AbstractObject {
public: /* 添加指定观察者 */ void Add(observer* ob) { observerList.push_back(ob); } /*
删除指定的观察者 */ void Remove(observer* ob) { observerList.remove(ob); cout << endl <<
ob->getName() << " is be removed" << endl << endl; } /* 通知所有观察者 */ void Notify(
) { auto it = observerList.begin(); while (it != observerList.end()) { (*it)->
update(); ++it; } } string action; private: list <observer*> observerList; };
/* 观察者的update方法实现 */ void observer::update() { cout << name << " : " << ob->
action<< endl; } int main() { /* 创建观察目标 */ Object* p = new Object(); /* 创建观察者 */
observer* s1 = new observer("observer1", p); observer* s2 = new observer(
"observer2", p); observer* s3 = new observer("observer3", p); observer* s4 = new
observer("observer4", p); /* 添加观察者到目标 */ p->Add(s1); p->Add(s2); p->Add(s3); p->
Add(s4); /* 事件产生 */ p->action = "first update"; /* 轮询通知 */ p->Notify(); /*
移除观察者s2 */ p->Remove(s2); /* 事件产生 */ p->action = "second update"; /* 轮询通知 */ p->
Notify(); }
<>具体应用程序示例
/** * Copyright: Copyright(c) 2019 * Created on 26/4/2019 * Author : ZYZMZM *
Version 1.0 * Title : Observer Pattern:Boss - 召唤师 **/ #include <iostream> #
include <list> using namespace std; /* 抽象观察者 */ class AbstractHero { public:
virtualvoid update() = 0; }; /* 具体观察者:召唤师1 */ class Hero1 : public AbstractHero
{ public: Hero1() { cout << "Hero1 join" << endl; } void update() { cout <<
"Hero1 stop to attack Boss" << endl; } }; /* 具体观察者:召唤师2 */ class Hero2 : public
AbstractHero{ public: Hero2() { cout << "Hero2 join" << endl; } void update() {
cout<< "Hero2 stop to attack Boss" << endl; } }; /* 具体观察者:召唤师3 */ class Hero3 :
public AbstractHero{ public: Hero3() { cout << "Hero3 join" << endl; } void
update() { cout << "Hero3 stop to attack Boss" << endl; } }; /* 具体观察者:召唤师4 */
class Hero4: public AbstractHero { public: Hero4() { cout << "Hero4 join" <<
endl; } void update() { cout << "Hero4 stop to attack Boss" << endl; } }; /*
抽象目标 */ class AbstractBoss { public: /* 添加观察者 */ virtual void Add(AbstractHero*
hero) = 0; /* 删除观察者 */ virtual void Remove(AbstractHero* hero) = 0; /* 通知所有观察者
*/ virtual void Notify() = 0; }; /* 具体目标:Boss */ class Boss : public
AbstractBoss{ public: /* 添加观察者 */ void Add(AbstractHero* hero) { heroList.
push_back(hero); } /* 删除观察者 */ void Remove(AbstractHero* hero) { heroList.remove
(hero); } /* 通知所有观察者 */ void Notify() { auto it = heroList.begin(); while (it !=
heroList.end()) { (*it)->update(); ++it; } } private: list <AbstractHero*>
heroList; }; int main() { /* 创建观察者:4位召唤师 */ AbstractHero* hero1 = new Hero1;
AbstractHero* hero2 = new Hero2; AbstractHero* hero3 = new Hero3; AbstractHero*
hero4= new Hero4; /* 创建目标:Boss */ AbstractBoss* bossA = new Boss; /* 添加观察者到目标 */
bossA->Add(hero1); bossA->Add(hero2); bossA->Add(hero3); bossA->Add(hero4); /*
移除观察者三号召唤师 */ cout << endl << "Hero3 die, Remove Hero3" << endl << endl; bossA->
Remove(hero3); /* 轮询通知 */ cout << endl << "Boss die, Notify other heros" << endl
<< endl; bossA->Notify(); }
参考:
刘伟《设计模式》
程杰《大话设计模式》

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信