C++设计模式——观察者模式

观察者模式(Observer)

动机(Motivation)

在软件构建过程中,我们需要为某些对象建立一种 “通知依赖关系 ” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好的抵御变化。

使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

模式定义

定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新 ——《设计模式》GoF

结构(Structure)

在这里插入图片描述

实例

场景

想象如下一个场景: 一群码农正在摸鱼,但又害怕老板突然到来,于是非常小心,不停需要抬头看向门口。 于是形成一种观察与被观察的关系,摸鱼码农需要观察门口是否有老板到来的情况。

在这里插入图片描述

这样就很头疼,摸鱼不能好好摸,担惊受怕的。 于是大家决定,选出一个’哨兵’,站在门口,当出现事件时(老板来了),就通知他们,这样就可以放心 摸鱼。

在这里插入图片描述

这样关系进行了转换,现在大家只需要等待哨兵的信号即可。而哨兵则要专心关注门口的动静,以便及 时通知大家。

代码实现
class Subject;
class Observer//抽象观察者
{
protected:
	string m_name;
	Subject* m_sub;

public:
	Observer(const string& name, Subject* sub)
		:m_name(name), m_sub(sub)
	{
		cout << "Create Observer" << endl;
	}
	~Observer()
	{
		cout << "Destroy Observer" << endl;
	}
	virtual void update() = 0;
};
class Programmer : public Observer
{
public:
	Programmer(const string& name, Subject* sub)
		:Observer(name, sub) {
		cout << "Programmer() " << endl;
	}
	~Programmer() { cout << "~Programmer()" << endl; }
	void update()
	{
		cout << m_name << " 接收到信息 " << endl;
		if (m_sub->hasChanged())
		{
			cout << m_sub->getMess() << " 停止摸鱼, 认真工作中..." << endl;
		}
		else
		{
			cout << " 老板没有来上班 ! " << m_sub->getMess() << endl;
		}
	}
};
class Subject//抽象被观察者,建立与观察之间的关系,提供notify接口
{
protected:
	std::list<Observer*> _obslist; //
	bool _is_boss; // true ; false;
	std::string _mess;
public:
	Subject() :_is_boss(false), _mess("摸鱼!") {}
	~Subject() { detachAll(); }
	void setChanged()
	{
		_is_boss = true;
		_mess = "老板来了!";
	}
	void clearChanged()
	{
		_is_boss = false;
		_mess = "老板没有来了!";
	}
	bool hasChanged() const { return _is_boss; }
	const string& getMess() const { return _mess; }
	void attach(Observer* obs)
	{
		_obslist.push_back(obs);
	}
	void detach(Observer* obs)
	{
		_obslist.remove(obs);
	}
	void detachAll()
	{
		_obslist.clear();
	}
	virtual void notify() = 0;
};

class Guard : public Subject
{
public:
	Guard() {
		cout << "create guard" << endl;
	}
	~Guard()
	{
		cout << "destroy guard" << endl;
	}
	void notify()
	{
		for (auto& x : _obslist)
		{
			x->update();
		}
	}
};

观察者模式的使用场景和优缺点

使用场景

关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。

事件多级触发场景。 跨系统的消息交换场景,如消息队列、事件总线的处理机制。

优点

实现了观察者和被观察者之间的抽象耦合。 动态联动

广播通信。被观察者会向所有的登记的观察者发出通知。

缺点

可能会引起无谓的操作。

由于采用广播方式,不管观察者需不需要,每个观察者都会被调用update方法 在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察 者,开发、调试等内容会比较复杂,在进行并发环境下,观察者卡顿,会影响整体的执行效率,在这种 情况下,一般会采用异步实现。

要点总结

  • 使用面向对象的抽象,Observer模式使得我们可以独立的改变目标与观察者,从而使二者之间的依赖关系达到松耦合
  • 目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播
  • 观察者自己决定是否需要订阅通知,目标对象对此一无所知
  • Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shang_Jianyu_ss

感谢大哥

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值