观察者模式

观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式的应用场景: 
1、 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。 
2、 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。


抽象主题(Subject)角色:主题角色把所有对观察考对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫做抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现。

抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。

具体主题(ConcreteSubject)角色:将有关状态存入具体现察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(Concrete Observable)。具体主题角色通常用一个具体子类实现。

具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体现察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。       


c++代码实现:

定义虚基类Subject与Observer

Subject类中需要保存所有它可以通知的对象,对象可用list存储,类型为Observer*类型,这样每次添加一个派生出的实际被观察角色对象时,相当于基类指针指向派生类对象,各个派生类对收到通知的接口各自实现,最后在通知时利用多态性质可以各自执行自己的操作。另外还需要提供添加对象,删除对象,以及通知的接口。

Observer类当做一个抽象类,只需要定义一个纯虚函数virtual void update()=0;即可。各个派生类对它重新实现后,即可在通知时做出不同的反应

ConcretSubject相当于秘书一般对Subject类的各个操作具体实现,并可以自己添加一些特有的功能,如通知某一个对象,通知某一组对象等等,此外,发送者还可以有自己的状态,在发送消息之前,对状态做修改后,各个响应操作里可以根据这个状态来做相应的操作。但是这时候需要思考一个问题,pConcretSubObj对象给ConcretObserver发送消息时,观察者知道是谁发送的吗?答案肯定是不知道的,既然不知道,那这个pConcreSubObj的状态又从何得知呢?所以可以在Observer类的成员变量中加入一个Subject 对象,在建立完一个ConCretSubject对象后再建立各个ConcretObserver对象时用前面的ConcretSubject对象来初始化Observer类中的这个Subject对象,这样ConcretSubject对象在收到通知时即可通过查看成员变量中的Subject对象的状态来做出反应。


这样便做到了一个消息发送多个对象,而消息对象同时也知道发送者是谁,根据状态来做出反应的需求。

下面给出c++代码实现

#include<iostream>
#include<string>
#include<list>
using namespace std;

class Observer
{
public:
	Observer() {}
	virtual void update() = 0;
};
class ObsDerive1 :public Observer
{
public:
	ObsDerive1() {}
	void update()
	{
		cout << "ObsDerive1收到了消息" << endl;
	}
};
class ObsDerive2 :public Observer
{
public:
	ObsDerive2() {}
	void update()
	{
		cout << "ObsDerive2收到了消息" << endl;
	}
};

class ObsDerive3 :public Observer
{
public:
	ObsDerive3() {}
	void update()
	{
		cout << "ObsDerive3收到了消息" << endl;
	}
};
class Subject
{
protected:
	list<Observer*>m_pObserverList;
public:
	Subject() {}
	virtual ~Subject() {}
	virtual void Notify() = 0;
	virtual void Add(Observer *obj) = 0;
	virtual void Remove(Observer *obj) = 0;
};
class ConcretSubject:public Subject
{
public:
	ConcretSubject() {}
	~ConcretSubject() {}
	//通知全部对象
	void Notify()
	{
		for (auto &p : m_pObserverList)
		{
			p->update();
		}
	}
	//通知单个某一个对象
	void Nofity(Observer *obj)
	{
		bool bExist = false;
		for (auto &p : m_pObserverList)
			if (obj == p)
				bExist = true;
		if (bExist)
			obj->update();
		else
			cout << "没有此对象" << endl;
	}
	void Add(Observer *obj)
	{
		m_pObserverList.push_back(obj);
	}
	void Remove(Observer *obj)
	{
		m_pObserverList.remove(obj);
	}
};
int main()
{
	ObsDerive1 *p1 = new ObsDerive1;
	ObsDerive2 *p2 = new ObsDerive2;
	ObsDerive3 *p3 = new ObsDerive3;
	ConcretSubject *pSub = new ConcretSubject;
	pSub->Add(p1);
	pSub->Add(p2);
	pSub->Add(p3);

	pSub->Notify();
	cout << endl;
	pSub->Nofity(p2);

	system("pause");
}
结果:
ObsDerive1收到了消息 
ObsDerive2收到了消息  
ObsDerive3收到了消息 
                       
ObsDerive2收到了消息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值