【学习笔记】C++下的观察者模式(程杰-大话设计模式)

【学习笔记】C++下的观察者模式(程杰-大话设计模式),第1张

引入:公司同事上班摸鱼,趁老板出门时看股票。为了防止被发现,与公司前台小姐姐达成共识,如果老板回来了,前台小姐姐提前通知公司同事,关闭股市行情网页,继续工作。


一、 双向耦合的实现:

Secretary.h

#pragma once
#include
#include
#include"StockObserver.h"

using namespace std;

class StockObserver;

class Secretary
{
private:
	vector observers;
	string m_action;

public:
	void Attach(StockObserver observer);

	void notify();

	void setAction(string action);

	string getAction();
};

Secretary.cpp

#include"Secretary.h"
#include"StockObserver.h"

void Secretary::Attach(StockObserver observer)
{
	observers.push_back(observer);
}

void Secretary::notify()
{
	for (auto it = observers.begin(); it != observers.end(); it++)
	{
		it->update();
	}
}

void Secretary::setAction(string action)
{
	m_action = action;
}

string Secretary::getAction()
{
	return m_action;
}

 StockObserver.h

#pragma once
#include
#include
#include"Secretary.h"

using namespace std;

class Secretary;

class StockObserver
{
private:
	string m_name;
	Secretary* m_sub;
public:
	StockObserver(string name, Secretary* sub);
	void update();

};

StockObserver.cpp

#include "StockObserver.h"
#include "Secretary.h"

StockObserver::StockObserver(string name, Secretary* sub)
{
	m_name = name;
	m_sub = sub;
}

void StockObserver::update()
{
	cout << m_sub->getAction() << m_name << "关闭股票,继续工作!" << endl;
}

客户端程序:

#include
#include"Secretary.h"
#include"StockObserver.h"

using namespace std;

int main()
{
	//Secretary xiaoJieJie;

	//StockObserver tongshi1("张三", &xiaoJieJie);
	//StockObserver tongshi2("李四", &xiaoJieJie);

	//xiaoJieJie.Attach(tongshi1);
	//xiaoJieJie.Attach(tongshi2);

	//xiaoJieJie.setAction("老板回来了!");

	//xiaoJieJie.notify();

	Secretary* xiaoJiejie = new Secretary;
	StockObserver* tongshi1 = new StockObserver("张三", xiaoJiejie);
	StockObserver* tongshi2 = new StockObserver("李四", xiaoJiejie);

	xiaoJiejie->Attach(*tongshi1);
	xiaoJiejie->Attach(*tongshi2);

	xiaoJiejie->setAction("老板回来了!");

	xiaoJiejie->notify();

	system("pause");

	xiaoJiejie = NULL;
	delete xiaoJiejie;
	tongshi1 = NULL;
	delete tongshi1;
	tongshi2 = NULL;
	delete tongshi2;

	return 0;
}

运行结果:

 二、解耦实践一

现在,有可能又有同事想看看NBA直播,之前的代码并没有定义一个观看NBA直播的同事的类。

定义一个抽象的Observer类,

Observer.h

#pragma once
#include
#include"Secretary.h"

using namespace std;

class Secretary;

class Observer
{
private:
	string m_name;
	Secretary* m_sub;
public:
	Observer() = default;
	Observer(string name, Secretary* sub);
	virtual void Update();
	~Observer() = default;
};

 Observer.cpp

#include "Observer.h"

Observer::Observer(string name, Secretary* sub)
{
	this->m_name = name;
	this->m_sub = sub;
}

void Observer::Update()
{
	cout << "Observer的update方法" << endl;
}

定义看股票的观察者:

StockObserver.h

#pragma once
#include
#include
#include"Observer.h"

using namespace std;

class StockObserver : public Observer
{
public:
	StockObserver(string name, Secretary* sub);
	virtual void Update();
private:
	string name;
	Secretary* sub;
};

StockObserver.cpp

#include "StockObserver.h"

StockObserver::StockObserver(string name, Secretary * sub)
{
	this->name = name;
	this->sub = sub;
}

void StockObserver::Update()
{
	cout << this->sub->getAction() << this->name << "关闭股票,继续工作!" << endl;
}

定义看NBA直播的观察者:

NBAObserver.h

#pragma once
#include
#include
#include"Observer.h"

using namespace std;

class NBAObserver : public Observer
{
public:
	NBAObserver(string name, Secretary* sub);
	virtual void Update();
private:
	string name;
	Secretary* sub;
};

NBAObserver.cpp

#include "NBAObserver.h"

NBAObserver::NBAObserver(string name, Secretary * sub)
{
	this->name = name;
	this->sub = sub;
}

void NBAObserver::Update()
{
	cout << this->sub->getAction() << this->name << "关闭NBA,继续工作!" << endl;
}

定义前台小姐姐类:

Secretary.h

#pragma once
#include
#include
#include"Observer.h"

using namespace std;

class Observer;

class Secretary
{
private:
	// vector observers; //  错误写法
    vector observers; // 正确写法
	string m_action;

public:
	// void Attach(Observer observer); 错误写法
    void Attach(Observer* observer);  对应修改

	void Detach(Observer observer);

	void Notify();

	string getAction();

	void setAction(string action);

};

【update】

注意Secretary类中的成员变量vector observers; 

这里错误的存储了基类,应该存储基类对象的指针类型。

正确写法应该是vector observers;

Secretary.cpp

#include "Secretary.h"

// void Secretary::Attach(Observer observer)
void Secretary::Attach(Observer* observer)  // 对应修改
{
	observers.push_back(observer);
}

void Secretary::Detach(Observer observer)
{
	observers.pop_back();
}

void Secretary::Notify()
{
	for (auto it = observers.begin(); it != observers.end(); it++)
	{
		// it->Update();
		(*it)->Update(); // 对应修改
	}
}

string Secretary::getAction()
{
	return m_action;
}

void Secretary::setAction(string action)
{
	m_action = action;
}

客户端程序:

#include
#include"Secretary.h"
#include"NBAObserver.h"
#include"StockObserver.h"

using namespace std;

int main()
{
	//Secretary xiaoJieJie;

	//StockObserver tongshi1("", xiaoJieJie);
	//NBAObserver tongshi2("张三" , xiaoJieJie);

	//xiaoJieJie.Attach(tongshi1);
	//xiaoJieJie.Attach(tongshi2);

	//xiaoJieJie.setAction("老板回来了!");

	//xiaoJieJie.Notify();

	Secretary* xiaoJiejie = new Secretary;
	Observer* tongshi1 = new StockObserver("张三", xiaoJiejie);
	Observer* tongshi2 = new NBAObserver("李四", xiaoJiejie);

	// xiaoJiejie->Attach(*tongshi1);
	// xiaoJiejie->Attach(*tongshi2);
	xiaoJiejie->Attach(tongshi1);
	xiaoJiejie->Attach(tongshi2);  // Secretary类update的对应修改

	xiaoJiejie->setAction("老板回来了!");

	xiaoJiejie->Notify();

	system("pause");

	xiaoJiejie = NULL;
	delete xiaoJiejie;
	tongshi1 = NULL;
	delete tongshi1;
	tongshi2 = NULL;
	delete tongshi2;

	return 0;
}

但是为什么我的程序中子类不能重写父类的Update方法啊,T^T……

运行结果:

三、继续解耦

 定义抽象的通知者和抽象的观察者,减少相互之间的依赖。

至于代码,不想写了……难受。

四、观察者模式*

观察者模式又叫分发布-订阅(Publish/Subscribe)模式。

五、附录——常见错误(error C2079) 

参考资料:《大话设计模式》,作者:程杰

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/914797.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存