观察者模式

观察者模式是一种设计模式,它定义了一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。适用场景包括对象间存在相互依赖、需要独立变更和重用,以及避免紧密耦合。天气预报订阅是典型的观察者模式实例,手机作为观察者,接收并更新天气信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这几天由于一直在研究智能指针,由weak_ptr解决shared_ptr的循环引用问题得到了weak_ptr是shared_ptr的观察者模式(又称发布-订阅模式)的理论。但是观察者模式是怎么回事呢。先引用一段设计模式的原文:

Intent :
Define a one-to-many dependency between objects so that when oneobject changes state, all its dependents are notified and updated automatically.

即在被观察者和观察者之间定义一个一对多的依赖关系,当被观察者状态改变时,观察者就会被通知并且更新其状态。

Applicability:

应用:

When an abstraction has two aspects, one dependent on the other.Encapsulating these aspects in separate objects lets you vary and reuse them independently.
情况一:有两个事件,一个依赖于另一个,可以分别封装这两个事件以提高变化性和重用性。
When a change to one object requires changing others, and you don't know how many objects need to be changed.
情况二:当一个对象的改变会引起其他的对象的改变,而你又不知道会影响多少个的时候。
When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.
情况三:当一个对象需要通知其他对象而又不想知道他们是谁的时候。换句话说就是不想让这些对象耦合太紧的时候。(个人感觉是跟第二个说的一回事)

下面是官方的UML图:

很常见的例子为天气预报订阅,手机可以订阅某些城市的天气情况,那么手机就是这些地区天气情况的观察者,当天气发生改变时通知到手机,手机再更新本地的天气情况的信息。

下图是我仿写的一个简单的例子来说明。首先给出UML图


#ifndef OBSERVER_H
#define OBSERVER_H
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <list>
using namespace std;
using namespace boost;
class IObserver//Observer接口类
{
public:
	virtual void UpdateInfo(int id)=0;
};
class ISubject//被观察者Target接口类
{
public:
	virtual void Register(shared_ptr<IObserver> observer)=0;
	virtual void ObserverRemove(shared_ptr<IObserver> observer)=0;
	virtual void Notify()=0;
};
#endif
#include "Observer.h"
using namespace std;
using namespace boost;

class A : public IObserver
{
public:
	A(int id):tid(id){}
	void UpdateInfo(int id);
private:
	int tid;

};

void A::UpdateInfo(int id)
{
	cout << id << endl;
}

class D:public ISubject
{
public:
	D(int str):id(str){};
	void Register(shared_ptr<IObserver> observer);
	void ObserverRemove(shared_ptr<IObserver> observer);
	void Notify();
private:
	list<shared_ptr<IObserver>> ListofObserver;//每个被观察者都有一个存贮观察者的指针的容器。以方便对多个观察者进行通知
	int id;
};

void D::Register(shared_ptr<IObserver> observer)//注册函数,用于存贮观察者的指针
{
	ListofObserver.push_back(observer);
}
void D::ObserverRemove(shared_ptr<IObserver> observer)//移除函数,用于移除观察者,也就是说被观察者有权解除观察者的观察
{
	ListofObserver.remove(observer);
}
void D::Notify()//通知观察者,这里一般都是调用观察者提供的方法,或者返回给观察者一个状态
{
	for(list<shared_ptr<IObserver>>::iterator it = ListofObserver.begin();it != ListofObserver.end();++it)
	{
		(*it)->UpdateInfo(id);
	}
}
int main(int,char**)
{
	shared_ptr<IObserver> p1(new A(1));//
	shared_ptr<IObserver> p2(new A(2));//构建两个观察者
	shared_ptr<ISubject> p3(new D(3));//
	shared_ptr<ISubject> p4(new D(4));//构建两个被观察者

	p3->Register(p1);
	p4->Register(p2);//分别注册

	p3->Notify();
	p4->Notify();//分别通知

}
上面的代码只是表达了两个观察者分别订阅两个被观察者的例子,之所以这个模式被称为订阅-发布模式也是这个道理,由于多态性,发布者不需要知道究竟谁订阅过,只需要在状态改变的时候发布即可,若干订阅者自会收到状态改变的通知的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值