定义
观察者模式(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返回的迭代器位置开始,一直到向量的末尾,删除这些元素。