设计模式-observer观察者模式

本文介绍了一种常用的设计模式——观察者模式。通过定义一对多的依赖关系,使得一个对象的状态改变能够通知到所有依赖它的对象。文章提供了一个具体的实现案例,包括主题(Subject)和观察者(Observer)的角色定义及交互过程。

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

    定义        

      观察者模式-在对象间定义一对多的依赖关系,这样一来当一个对象的状态更新时,其它对象都能得到通知更新。主题并不需要了解观察者具体实现细节,只需要保证观察者实现了观察者接口即可。

  1. 观察者模式定义了对象间一对多的关系。即一个主题,多个观察者观察主题的状态变化。
  2. 主题通过某个公共的接口来通知观察者。
  3. 不要依赖于特定的通知顺序。除非设计一个能明确通知顺序的主题。
  4. 一般来说主题对观察者通知是串行的,因此尽量不要在观察者的通知接口中作出繁重的工作
    类图

     在这里定义了主题的接口ISubject,拥有注册的attach接口和取消注册的detach接口。还有个protected的notify接口通知所有观察者。观察者通过on_notify接口得到通知。

    主题实现的是CRoomTemperature类,代表室内温度。有个set_temperature接口设定温度然后触发通知观察者。观察者实现的是CPannel面板,通过on_notify接口得到室温变化,并更新自己的显示。

               

    实现
#include <stdio.h>
#include <string>
#include <map>

#define trace(fmt, ...) printf("[trace] %s:%s:%d " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)

class IObserver
{
	public:
		virtual ~IObserver(){};
		virtual void on_notify(void *, void *) = 0;
};
class ISubject
{
	public:
		virtual ~ISubject(){};
		virtual int attach(IObserver *, void *) = 0;
		virtual int detach(IObserver *) = 0;
	protected:
		virtual int notify(void *) = 0;
};
class CRoomTemperature: public ISubject
{
	public:
	 	int attach(IObserver *observer, void *arg = NULL);
		int detach(IObserver *);
		int set_temperature(double temp);
	protected:
		int notify(void *);
	private:
		typedef std::map<IObserver *, void *> observermap_t;
		typedef observermap_t::iterator observermap_itor_t;
		typedef std::pair<observermap_itor_t, bool> observermap_ret_t;
		typedef std::pair<IObserver *, void *> observermap_pair_t;

		observermap_t observermap;
		double temp;
};
int CRoomTemperature::attach(IObserver *observer, void *arg)
{
	if(observer == NULL)
		return -1;
	if(observermap.find(observer) != observermap.end())	//already exist
		return 0;
	observermap_ret_t ret = observermap.insert(observermap_pair_t(observer, arg));
	if(ret.second == false)
		return -1;
	return 0;
}
int CRoomTemperature::detach(IObserver *observer)
{
	if(observer == NULL)
		return -1;
	observermap_itor_t itor = observermap.find(observer);
	if(itor == observermap.end())	// not found
		return -1;
	observermap.erase(itor);
	return 0;
}
int CRoomTemperature::set_temperature(double temp)
{
	this->temp = temp;
	notify((void *)&temp);
	return 0;
}
int CRoomTemperature::notify(void *data)
{
	observermap_itor_t itor = observermap.begin();
	for(; itor != observermap.end(); itor++){
		IObserver *observer = (*itor).first;
		void *arg = (*itor).second;

		observer->on_notify(data, arg);	 // notify object
	}
	return 0;
}

class CPanel: public IObserver
{
	public:
		void on_notify(void *data, void *arg)
		{
			double temp = *(double *)data;
			trace("no notify, temperature: %f\n", temp);
		}
};
int main(int argc, char **argv)
{
	CRoomTemperature roomtemp;
	CPanel panel;

	roomtemp.attach(&panel);

	roomtemp.set_temperature(18.2);
	roomtemp.set_temperature(22.2);
	return 0;
}

   

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值