【设计模式】[观察者模式的]程序实例C++ 以及观察者模式与事件监听的区别
转自:https://www.cnblogs.com/mfrbuaa/p/4364678.html
一、什么是观察者模式
Observer模式也叫观察者模式,它的作用是当一个对象的状态发生变化时,可以自己主动通知其它关联对象,自己主动刷新对象状态。
举个样例,用户界面能够作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
“观察”不是“直接调用”
实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。不管是观察者“观察”对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。
实现观察者模式的形式
实现观察者模式有非常多形式,比較直观的一种是使用一种“注冊——通知——撤销注冊”的形式。
实现观察者模式样例
以下是C++的实现,在C++实现中,C++中没有接口的概念,可是能够用抽象类类取代Java或C#中的接口,在C++中抽象类中从派生类中抽象出来的函数(方法),必须定义成纯虚函数,这样在后面的使用中才干够通过基类的指针来訪问这些函数,面向对象的语言中有个特点,多态仅仅能訪问两者中共同拥有的部分。
//实例源自http://blog.csdn.net/ocean181/archive/2010/09/11/5877621.aspx#1607956 ,主要做了点修正.
#include <iostream>
#include <list>
#include <string>
using namespace std;
class Observer;//声明提前
class Subject
{
public:
virtual void attach(Observer *o) = 0;
virtual void change() = 0;
virtual void setWeather(string str) = 0;
virtual string getWeather() = 0;
};
class Observer
{
public:
virtual string getName() = 0;
virtual void update(Subject *s) = 0;
};
class Earth: public Subject //被观察对象
{
private:
string weather;
list<Observer * > *l; //指针
public:
Earth()
{
l = new list<Observer *>;
}
void attach(Observer *o)
{
this->l->push_back(o);
};
void change() //变量“通知”观察者(变量执行注册的观察者的方法)
{
for(list<Observer *>::iterator it = l->begin(); it != l->end(); ++it)
{
(*it)->update(this);
}
};
void setWeather(string str)
{
this->weather = str;
change();
};
string getWeather()
{
return this->weather;
};
};
class Satellite: public Observer
{
private:
string name;
public:
Satellite(string str)
{
name = str;
}
string getName()
{
return name;
};
void update(Subject *s)
{
cout << this->getName() + " " + s->getWeather();
}
};
int main()
{
Earth e;
Satellite *s1 = new Satellite("风云一号");
Satellite *s2 = new Satellite("风云二号");
Satellite *s3 = new Satellite("风云三号");
Satellite *s4 = new Satellite("风云四号");
e.attach(s1);
e.attach(s2);
e.attach(s3);
e.attach(s4);
e.setWeather("fine");
while(1) {}
return 0;
}
观察者模式和事件监听模式的区别
转自:https://blog.csdn.net/AXuan_K/article/details/78803382?utm_source=blogxgwz1
说到事件监听模式,很容易将它和观察者模式联系在一起。
实质上这两者完成同类型的工作。依个人理解,事件监听模式更像是观察者模式的进阶。
用一张图来方便描述它们的区别:
观察者模式中,‘主题’会在特定逻辑下通知所有‘观察者’。
如果这个通知不包含任何信息,那么这种实现就是通常的观察者模式。
class Subject
{
protected:
void notify()
{
for (int i = 0; i < numObservers_; i++)
{
observers_[i]->onNotify();
}
}
};
如果‘主题’通知‘观察者’的过程带有一些<其他信息>。那么‘主题’本身已经上升成为了‘事件源’,
而通知中带有的<其他信息>经过封装就成为了事件。
class Subject
{
protected:
void notify(const Entity& entity, Event event)
{
for (int i = 0; i < numObservers_; i++)
{
observers_[i]->onNotify(entity, event);
}
}
};
事件监听模式的优势:
在很多应用场景中,通知中附带的<其他信息>是必不可少的,
事件Event则对这些<信息>进行了封装,使它本身拥有了多态的特性。
每个事件对象就可以包含不同的信息。但各个‘观察者’提供给‘主题’的接口仍然是统一的 :
onNotify(entity, event)
举个简单的例子,某游戏中的成就系统包含两种成就:
1.达成等级成就(观察者1) 2.达成战斗力成就(观察者2)
玩家(事件源)在完成升级时会创建两个对象,
升级事件(包含玩家等级字段) 战斗力提升事件(包含玩家当前战斗力字段)。
成就系统收到事件后执行统一的逻辑:
observers_[event.type]->OnAchieveEvent(entity, event);
总结来说 事件监听机制就是对观察者模式进行了进一步抽象,节省了代码量。
---------------------
作者:AXuanK
来源:CSDN
原文:https://blog.csdn.net/AXuan_K/article/details/78803382
版权声明:本文为博主原创文章,转载请附上博文链接!
观察者模式===》发布订阅者模式。
发散学习:发布-订阅者模式和事件监听器模式
https://www.jianshu.com/p/40986c26315a
项目经验:
用户表数据改变后, 共享内存(观察者1)里的 数据要改变 ,数据库里 版本表(观察者2)的记录也要改变。