设计模式---观察者模式

113 阅读3分钟

定义

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象的状态发生变化时,所有依赖于它的观察者对象都会得到通知并自动更新。

结构

  • 主题(Subject) :被观察的对象,它持有观察者的集合,可以增加和删除观察者。它在自身状态发生变化时通知所有观察者。

  • 观察者(Observer) :定义一个更新接口以便接收主题的更新通知。

  • 具体主题(Concrete Subject) :具体的被观察对象,它在内部状态改变时通知所有登记的观察者。

  • 具体观察者(Concrete Observer) :具体的观察者实现,它在接收到更新通知后执行相应的操作。

特点

  • 松耦合

    观察者模式使得观察者和主题之间的关系松散。主题只需知道观察者实现了某个接口,不需要知道观察者的具体实现。这种松耦合提高了系统的灵活性和可扩展性。

  • 动态依赖关系

    观察者可以在运行时动态地注册和取消注册,这使得系统能够动态地增加或删除观察者。

  • 广播通信

    主题向所有注册的观察者广播通知,而不需要知道具体有哪些观察者。观察者自动接收更新并执行相应的操作。

  • 单向依赖

    观察者依赖于主题,而主题并不依赖于具体的观察者。这种单向依赖关系有助于降低系统的复杂度。

代码示例

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

// 观察者接口
class Observer
{
public:
	virtual ~Observer() = default;
	virtual void update(const std::string& message) = 0;
};


// 主题接口
class Subject
{
public:
	virtual ~Subject() = default;
	virtual void attach(Observer*) = 0;
	virtual void detach(Observer*) = 0;
	virtual void notify() = 0;
};


// 具体主题
class ConcreteSubject :public Subject
{
private:
	std::vector<Observer*> observers;
	std::string state;

public:
	void attach(Observer* observer) override
	{
		observers.push_back(observer);
	}

	void detach(Observer* observer) override
	{
		observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
	}

	void notify() override
	{
		for (Observer* observer : observers)
		{
			observer->update(state);
		}
	}

	void setState(const std::string& newState)
	{
		state = newState;
		notify();
	}

	std::string getState() const
	{
		return state;
	}
};


// 具体观察者
class ConcreteObsrever :public Observer
{
private:
	std::string name;

public:
	ConcreteObsrever(const std::string& name) : name(name) {}

	void update(const std::string & message) override
	{
		std::cout << "Observer " << name << ": Subject state changed to " << message << std::endl;
	}
};


int main()
{
	ConcreteSubject subject;

	ConcreteObsrever observer1("observer1");
	ConcreteObsrever observer2("observer2");

	subject.attach(&observer1);
	subject.attach(&observer2);

	subject.setState("State 1");
	subject.setState("State 2");

	subject.detach(&observer1);

	subject.setState("State 3");

	system("pause");
	return 0;
}

observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end()); :

  • std::remove 函数

    • std::remove 是一个标准库算法,它并不会真正删除元素,而是重新排列元素,将所有不需要的元素移到向量的末尾,同时返回一个指向新逻辑末尾的迭代器。
    • 在这里,std::remove 将所有与 observer 相等的元素移到 observers 向量的末尾,并返回一个指向第一个被“移除”的元素的位置的迭代器。
  • observers.begin()observers.end()

    • 这些函数返回向量的开始和结束迭代器,分别用于指定 std::remove 的操作范围。
  • observers.erase 函数

    • erase 函数会删除指定范围内的元素。传入的参数是两个迭代器,表示要删除的元素范围。
    • 在这里,erase 函数从 std::remove 返回的迭代器位置开始,一直到向量的末尾,删除这些元素。