Head First 设计模式——chapter2 观察者模式C++实现

观察者模式: 出版者+订阅者

主题对象(出版者)管理某些数据,当主题内的数据改变,就会通知观察者(订阅者)。

观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。相比让多个对象控制同一份数据,可以得到更干净的OO设计。

设计原则:

为了交互对象之间的松耦合努力。

改变一方都不会影响另一方。两者松耦合,但他们仍然可以交互,只要交互原则仍被遵守。松耦合能让我们建立有弹性的OO系统,将对象之间的互相依赖降到最低。

可观察者不知道观察者的细节,只知道观察者实现了观察者接口。

tips:

信息更新可以推给观察者或者观察者从主题对象拉。(推更适用)。

代码实现:


//观察者抽象类
class Observer {
public:
	virtual void update(float tmp, float hum, float pre) = 0;
    virtual ~Observer(){}
};

//展示抽象类
class Display {
public:
	virtual void display() const = 0;
    virtual ~Display (){}
};

//主题抽象类
class Subject {
public:
	virtual void registerObserver( Observer* b) = 0;
	virtual void removeObserver( Observer* b) = 0;
	virtual void notifyObserver() = 0;
    virtual ~Subject (){}
};

class WeatherData :public Subject {
private:
	std::vector<Observer*> observers;
	float temperature=0;
	float humidity=0;
	float pressure=0;

public:
	WeatherData() :Subject() {	}

	void registerObserver( Observer* b)
	{
		observers.push_back(b);
	}

	void removeObserver(Observer* ob)
	{
		auto it = find(observers.begin(), observers.end(), ob);
		if (it != observers.end())
			observers.erase(it);
	}
	//通知观察者,使得所有观察者更新信息。
	void notifyObserver()
	{
		for (auto& it : observers)
			it->update(temperature, humidity, pressure);
	}

	void measurementsChanged()
	{
		notifyObserver();
	}

	//设置气象站天气信息并通知观察者。
	void setMeasurements(float tmp, float hum, float pre)
	{
		temperature = tmp;
		humidity = hum;
		pressure = pre;
		measurementsChanged();
	}

	~WeatherData()
	{
		for (auto& each : observers)
		{
			delete each;
			each = nullptr;
		}
	}

};

class CurrentConditionsDisplay :public Observer, public Display {
private:
	float temperature=0;
	float humidity=0;
	Subject* weatherData=nullptr;

public:
	//初始化信息板,并在气象站对其登记。
	CurrentConditionsDisplay(Subject* wd) :Observer(), Display()
	{
		weatherData = wd;
		weatherData->registerObserver(this);
	}
	//更新天气信息并展示。
	void update(float tmp, float hum, float pre)
	{
		temperature = tmp;
		humidity = hum;
		display();
	}

	void display() const
	{
		printf("Current conditions: %.2f F degrees and %.2f %% humidity\n", temperature, humidity);
	}
	
	~CurrentConditionsDisplay()
	{
		if (weatherData)
		{
			delete weatherData;
			weatherData = nullptr;
		}
	}
};

int main()
{
	{
		WeatherData* wd = new WeatherData();
		CurrentConditionsDisplay* cd = new CurrentConditionsDisplay(wd);

		//wd修改天气信息 并通知展示板
		wd->setMeasurements(80, 65, 30.4f);
		wd->setMeasurements(60, 35, 32.1f);
		wd->removeObserver(cd);
		wd->setMeasurements(60, 35, 31.1f);
	}
	system("pause");
}

别的适用场合:

比如按钮按下的监听事件,不同的监听者即是观察者。按钮按下会通知监听者,执行对应的操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值