c++ 设计模式23讲之观察者模式

/*编程小技巧
1.声明和定义最好分别写在.h和.cpp文件,避免循环依赖
2.前向声明只能使用指针和引用的声明,不能初始化对象和调用方法
3.共同的方法最好集成在基类,避免代码冗余
4.代码是人看的,不要用很炫的技巧把自己坑了
5.virtual override static可以用在声明但不能用在定义
6.inline要用在定义开头,用在声明无效
7.避免转成基类截断,最好用智能指针或者boost库
8.小心类对象的重新生成,成员变量状态不一致,最好采用注入依赖而不是成员变量*/

观察者模式

定义:

定义对象之间一种一对多的依赖关系,实现莫一对象状态改变时同步通知更新依赖对象

优点:

(1)起到MVC作用将表示层与逻辑层隔离,采用消息传递扩展观察者角色

(2)观察者模式支持广播通信,实现1对多的通信机制

(3)观察目标和观察者建立抽象耦合,观察目标维护观察者集合,无需关系观察者真正动作

缺点:

(1)观察目标有很多观察者会造成每个都通知到,消耗时间

(2)存在循环依赖,耦合性高

使用范围:

存在1对多的依赖关系,并需要广播通信的系统,如MVC,群聊,委托事件等

结构:

实现一个聊天室功能,实现一人发消息触发其他人响应

实现:

namespace behavioral_pattern
{
	class member;
	class msg_info;

	class observer_pattern
	{
	public:
		virtual void add(std::shared_ptr<member> mem) = 0;
		virtual void del(std::shared_ptr<member> mem) = 0;
		virtual void notify(msg_info& msg) = 0;
	};

	class room_observer_pattern : public observer_pattern
	{
	public:
		virtual void add(std::shared_ptr<member> mem) override;
		virtual void del(std::shared_ptr<member> mem) override;
		virtual void notify(msg_info& msg) override;
	private:
		std::vector<std::shared_ptr<member>>list_mem{};
	};
}

namespace behavioral_pattern
{
	class msg_info
	{
	public:
		msg_info(std::string m, unsigned long i) :msg(m), id(i) {};
		std::string msg{};
		unsigned long id{ 0 };
	};

	class member
	{
	public:
		virtual void update();
		virtual void call_notify(std::shared_ptr<observer_pattern> room);
		virtual int get_id() = 0;
	protected:
	};

	class mom_member : public member
	{
	public:
		int get_id() override;
	};

	class son_member : public member
	{
	public:
		int get_id() override;
	};
}
//定义代码
void behavioral_pattern::room_observer_pattern::add(std::shared_ptr<member> mem)
{
	list_mem.push_back(mem) ;
}
void behavioral_pattern::room_observer_pattern::del(std::shared_ptr<member> mem)
{
	for(auto itr= list_mem.begin();itr!=list_mem.end();++itr)
	{
		if (itr->get()->get_id() == mem->get_id())
		{
			list_mem.erase(itr);
			break;
		}
	}
}
void behavioral_pattern::room_observer_pattern::notify(msg_info& msg)
{
	for each(auto itr in list_mem)
	{
		if (itr->get_id() != msg.id)
		{
			itr->update();
		}
	}
}
void behavioral_pattern::member::update()
{
	std::cout << get_id() << "__accept" << std::endl;
}
void behavioral_pattern::member::call_notify(std::shared_ptr<observer_pattern> room)
{
	msg_info info("send msg", get_id());
	std::cout << get_id() << "__send msg" << std::endl;
	room->notify(info);
}
int behavioral_pattern::mom_member::get_id()
{
	return 1;
}
int behavioral_pattern::son_member::get_id()
{
	return 2;
}

测试:

基于GoogleTest 的单元测试框架;框架可参考如下网址:

https://www.cnblogs.com/jycboy/p/gtest_catalog.html

using namespace behavioral_pattern;

TEST(test_observer_pattern_add_notify, success_add_notify)
{
	std::shared_ptr<observer_pattern> obs{ new room_observer_pattern() };
	std::shared_ptr<member> mom{ new mom_member() };
	std::shared_ptr<member> son{ new son_member() };
	obs->add(mom);
	obs->add(son);
	son->call_notify(obs);
	mom->call_notify(obs);
}

总结

(1)观察者模式是常用模式,必须掌握的

(2)重点是观察目标维持观察者集合,广播通知

(3)注意触发条件,如果是观察者相互触发需要观察者依赖观察目标。并调用观察目标的通知接口

(4)详见开头编程技巧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
观察者模式(Observer Pattern)是一种行为型设计模式,它允许一个对象(称为主题或可观察者)在状态变化时通知其他多个对象(称为观察者)。这个模式主要用于解耦主题和观察者,使它们能够独立地进行修改和扩展。 在观察者模式,主题维护一个观察者列表,可以动态地添加或移除观察者。当主题的状态发生变化时,它会遍历观察者列表,并调用每个观察者的更新方法,将状态变化的信息传递给观察者。观察者可以根据接收到的信息做出相应的操作。 以下是一个简单的示例代码,演示了观察者模式的实现: ```c #include <iostream> #include <vector> // 观察者接口 class Observer { public: virtual void update(int data) = 0; }; // 具体观察者 A class ConcreteObserverA : public Observer { public: void update(int data) override { std::cout << "ConcreteObserverA received: " << data << std::endl; } }; // 具体观察者 B class ConcreteObserverB : public Observer { public: void update(int data) override { std::cout << "ConcreteObserverB received: " << data << std::endl; } }; // 主题 class Subject { private: int data; std::vector<Observer*> observers; public: void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { // 从观察者列表删除观察者 // ... } void notify() { for (Observer* observer : observers) { observer->update(data); } } void setData(int value) { data = value; notify(); } }; int main() { Subject subject; ConcreteObserverA observerA; ConcreteObserverB observerB; subject.attach(&observerA); subject.attach(&observerB); subject.setData(42); return 0; } ``` 在上述示例,`Subject` 是主题类,维护了一个观察者列表。`Observer` 是观察者接口,定义了一个 `update` 方法用于接收主题的通知。`ConcreteObserverA` 和 `ConcreteObserverB` 是具体的观察者类,实现了 `update` 方法。 在 `main` 函数,我们创建了一个主题对象 `subject` 和两个观察者对象 `observerA` 和 `observerB`。通过调用 `attach` 方法,将观察者对象添加到主题的观察者列表。然后,通过调用 `setData` 方法改变主题的状态,并自动通知所有观察者。 当 `subject.setData(42)` 被调用时,观察者 `observerA` 和 `observerB` 的 `update` 方法会被依次调用,输出相应的信息。 这就是观察者模式的基本实现。通过使用观察者模式,主题和观察者之间的耦合性降低,可以方便地扩展和修改代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值