行为模式——观察者模式

行为型模式: 关注系统中对象之间的相互交互,研究运行时对象之间的相互通信和协作,明确对象职。

观察者模式

建立对象间的一对多关系,使一个对象变化被所有关联对象感知。

角色

  1. 抽象主题(Subject):
    它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
  2. 具体主题(Concrete Subject):
    将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
  3. 抽象观察者(Observer):
    为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
  4. 具体观察者(Concrete Observer):
    实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

其中,主题提供了注册事件、销毁事件、通知方式等方法。
而抽象观察者是所有观察者的父类,我们添加新的观察者只需要继承抽象观察者类即可。
抽象主题类是所有通知者的父类,我们添加新的通知者只需要继承抽象主题类即可。

#include <iostream>
#include <list>
using namespace std;

struct MyObserver // 观察者
{
	virtual void response() = 0; // 相应方式
};
class Mouse : public MyObserver // 老鼠
{
public:
	void response() { cout << "老鼠拼命的逃包" << endl; }
};
class Dog : public MyObserver // 狗
{
public:
	void response() { cout << "狗跟着叫 ! " << endl; }
};

class MySubject // 主题
{
protected:
	std::list<MyObserver*> obslist;
public:
	void attach(MyObserver* obs)
	{
		obslist.push_back(obs);
	}
	void detach(MyObserver* obs)
	{
		obslist.remove(obs);
	}
public:
	virtual void cry() = 0;
};

// 通知者
class Cat : public MySubject
{
public:
	void cry()
	{
		cout << "猫叫 !" << endl;
		cout << "----------" << endl;
		for (auto& x : obslist)
		{
		x->response();
		}
	}
};

int main() // client
{
	MySubject* sp = new Cat();
	MyObserver* oba = new Mouse();
	MyObserver* obb = new Dog();
	// 建立猫与{狗、鼠}之间的关系
	sp->attach(oba);
	sp->attach(obb);
	sp->cry();

	// 现在不让狗得到此事件的通知
	sp->detach(oba);
	sp->cry();


	return 0;
}

示例2:

/*
	秘书通知员工模型
		秘书:吃饭		员工:收到,去吃饭
		秘书:boss到	员工:收到,马上努力工作
*/

#include <iostream>
#include <string>
#include <list>

class Subject;	// 事件中心,通知人的抽象类,负责通知观察者

class Observer	// 观察者抽象类
{
protected:
	std::string name;		// 员工姓名
	Subject* sub;			// 关联事件中心——秘书,根据事件中心的不同事件作出不同的应对策略
public:
	Observer(std::string nm, Subject* s)
		:name(nm), sub(s)	// 构造函数
	{}
	virtual ~Observer() {}	// 虚析构,注:多态继承中基类一定要写上虚析构
	// 事件通知后的响应方式
	virtual void update() const = 0;	// 纯虚函数
};
class StockObserver :public Observer	// 摸鱼:玩股票的员工
{
public:
	StockObserver(std::string nm, Subject* s) 
		:Observer(nm, s)
	{}
	void update() const override;
};
class NBAObserver : public Observer
{
public:
	NBAObserver(std::string nm,Subject* s)
		:Observer(nm,s)
	{}
	void update()const  override;
};


// 事件中心类,通知人的抽象类
class Subject
{
public:
	std::string event;	// 事件
protected:
	std::list<Observer*> observer;	// 观察者列表
public:
	virtual ~Subject() {}
	// 添加函数,把对应通知对象添加到列表中
	virtual void attach(Observer*) = 0;		// 添加关联
	virtual void detach(Observer*) = 0;		// 解除关联
	virtual void notify() = 0;		// 通知
};
class Secretary : public Subject
{
	virtual void attach(Observer* ob) override
	{
		observer.push_back(ob);
	}
	virtual void detach(Observer* ob) override
	{
		observer.remove(ob);
	}
	virtual void notify() override
	{
		for (auto& x : observer)
			x->update();	// 调用他们各自的消息处理函数
	}
};



/* -------------- 响应方式实现 -------------------*/
void StockObserver::update() const
{
	if (sub->event == "吃饭")
	{
		std::cout << "收到消息:" << sub->event << ",我马上去吃饭!" << std::endl;
	}
	else if (sub->event == "boss来了")
	{
		std::cout << "收到消息:" << sub->event << ",我马上关闭股票,努力工作!" << std::endl;
	}
}
void NBAObserver::update() const
{
	if (sub->event == "吃饭")
	{
		std::cout << "收到消息:" << sub->event << ",我马上去吃饭!" << std::endl;
	}
	else if (sub->event == "boss来了")
	{
		std::cout << "收到消息:" << sub->event << ",我马上关闭NBA ,努力工作!" << std::endl;
	}
}



int main()
{
	// 创建通知人 
	Subject* dwp = new Secretary();
	// 创建员工
	Observer* xm = new StockObserver("小明", dwp);
	Observer* dz = new StockObserver("大壮", dwp);
	Observer* zg = new NBAObserver("张刚", dwp);

	// 绑定观察关系
	dwp->attach(xm);
	dwp->attach(dz);
	dwp->attach(zg);

	// 注:这里的时间类型可通过枚举实现
	// 确定事件类型
	dwp->event = "吃饭";
	// 通知事件给绑定的观察者
	dwp->notify();

	// 确定事件类型
	dwp->event = "boss来了";
	dwp->notify();

	delete dwp;
	delete xm;
	delete dz;
	delete zg;

	return 0;
}

上述代码并不完美,如果我们能实现使用智能指针自动回收内存就很完美了。

这里我们只是在使用时用到了智能指针,更好的办法是将观察者模式设计成含有智能指针的版本。


int main()
{
	// 创建通知人 
	//std::unique_ptr<Subject> dwp(new Secretary());
	//std::shared_ptr<Subject> dwp  = std::make_shared<Secretary>();
	std::shared_ptr<Subject> dwp(new Secretary());
	// 创建员工
	std::unique_ptr<Observer> xm(new StockObserver("小明", dwp.get()));
	std::unique_ptr<Observer> dz(new StockObserver("大壮", dwp.get()));
	std::unique_ptr<Observer> zg(new NBAObserver("张刚", dwp.get()));

	// 绑定观察关系
	dwp->attach(xm.get());
	dwp->attach(dz.get());
	dwp->attach(zg.get());

	// 注:这里的时间类型可通过枚举实现
	// 确定事件类型
	dwp->event = "吃饭";
	// 通知事件给绑定的观察者
	dwp->notify();

	// 确定事件类型
	dwp->event = "boss来了";
	dwp->notify();

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我叫RT

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值