Bootstrap

行为型模式之观察者模式

一、概述

1、观察着模式:定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并自动更新

2、发生改变的对象称为观察目标,被通知的对象称为观察者

3、一个观察目标可以对应多个观察者

4、别名:发布-订阅模式、模型-视图模式、源-监听器模式、从属者模式

二、观察者模式的结构

观察者模式包含以个下4个角色:

Subject(主题):主题是一个包含观察者列表的抽象类或接口,它提供注册、删除、通知观察者的方法。当主题发生变化时,它会调用通知方法来更新所有注册的观察者

ConcreteSubject(具体主题):具体主题实现主题的接口,通常包含具体的状态或数据。当这些数据发生变化时,它会通知所有的观察者

Observer(观察者):观察者是一个抽象类或接口,定义了观察者接收到通知需要执行的操作

ConcreteObserver(具体观察者):具体观察者实现观察者的接口,并在接受到通知时执行具体操作

三、UML图

四、观察者模式的实现步骤

1、创建一个观察者接口(Observe)

class Observe
{
public:
	virtual ~Observe() = default;
	virtual void update(const string& message) = 0;
};

2、实现具体的观察者(ConcreteObserver)

class LOLObserve : public Observe
{
public:
	void update(const string &message) override
	{
		if (message == "夏季赛开播了")
			cout << "我准备要开始看游戏比赛了" << endl;
	}
};

class NBAObserve : public Observe
{
public:
	void update(const string& message)
	{
		if (message == "NBA比赛开始了")
			cout << "收到,准备进场";
	}
};

3、定义主题接口(Subject)

class Subject
{
public:
	virtual ~Subject() = default;
	virtual void addMember(std::shared_ptr<Observe> observe) = 0;
	virtual void removeMember(std::shared_ptr<Observe> observe) = 0;
	virtual void notify(const string &message) const = 0;

protected:
	vector<std::shared_ptr<Observe>> m_children;
};

4、实现具体主题(ConcreteSubject)

class ConcreteSubject : public Subject
{
public:
	void addMember(std::shared_ptr<Observe> observe) override
	{
		m_children.push_back(std::move(observe));
	}
	void removeMember(std::shared_ptr<Observe> observe) override
	{
		auto it = m_children.begin();
		while (it != m_children.end())
		{
			if (*it == observe)
			{
				m_children.erase(it);
				break;
			}
			++it;
		}
	}

	void notify(const string& message) const override
	{
		for (auto observe : m_children)
			observe->update(message);
	}
};

5、客户端使用

int main()
{
	std::shared_ptr<Observe> lolObserve = std::make_shared<LOLObserve>();
	std::shared_ptr<Observe> nbaObserve = std::make_shared<NBAObserve>();

	std::shared_ptr<Subject> subject = std::make_shared<ConcreteSubject>();
	subject->addMember(lolObserve);
	subject->addMember(nbaObserve);

	string message = "NBA比赛开始了";
	cout << message << endl;
	subject->notify("NBA比赛开始了");

	return 0;
}

6、输出结果

NBA比赛开始了
收到,准备进场

五、观察者模式适用的场景

1、事件驱动系统:当一个对象的状态变化时,需要通知其他依赖于该对象的多个对象,比如图形用户界面(GUI)系统中的按钮点击事件

2、数据变化通知:在数据模型与视图之间,视图需要根据数据的变化进行更新。比如在 MVC(模型-视图-控制器)架构中,模型的变化会通知视图进行更新。

3、发布-订阅系统:当一个对象(发布者)有多个对象(订阅者)需要接收消息或更新时,例如消息队列、通知系统等。

4、依赖关系动态管理:当一个对象的状态变化会影响到其他多个对象,而这些对象的数量和类型在运行时可能会变化。观察者模式可以动态地增加或删除观察者。

5、跨组件通信:在一些大型系统中,组件之间的耦合度需要最小化。观察者模式可以实现不同组件之间的低耦合通信。

六、模式优点

1、可以实现表示层和数据逻辑层的分离

2、在观察目标和观察者之间建立一个抽象的耦合

3、支持广播通信,简化了一对多系统设计的难度

4、符合开闭原则,增加新的具体观察者无需修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便

七、模式缺点

1、将所有观察者都通知到会花费很多时间

2、如果存在循环依赖可能导致系统崩溃

3、没有相应的机制让观察者知道所观察的目标对象是怎样变化的,而只是知道观察目标发生了变化

;