哈喽,各位盆友们!我是你们亲爱的学徒小z,今天给大家分享的文章是设计模式的------观察者模式。
定义
- 定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
通用类图
1.具体结构
-
Subject被观察者
定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类 或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。
-
Observer观察者
观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。
-
ConcreteSubject具体的被观察者
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
- ConcreteObserver具体的观察者
每个观察在接收到消息后的处理反应是不同,各个观察者有自己的处理逻辑
2.具体代码
c++
#include <iostream>
#include <vector>
#include <algorithm>
// 观察者接口
class Observer {
public:
virtual ~Observer() {}
virtual void update(const std::string& message) = 0;
};
// 被观察者接口
class Subject {
public:
virtual ~Subject() {}
virtual void subscribe(Observer* observer) = 0;
virtual void unsubscribe(Observer* observer) = 0;
virtual void notify(const std::string& message) = 0;
};
// 具体的观察者类
class ConcreteObserver : public Observer {
private:
std::string name;
public:
ConcreteObserver(const std::string& name) : name(name) {}
void update(const std::string& message) override {
std::cout << name << " received notification: " << message << std::endl;
}
};
// 具体的被观察者类
class ConcreteSubject : public Subject {
private:
std::vector<Observer*> observers;
public:
void subscribe(Observer* observer) override {
observers.push_back(observer);
}
void unsubscribe(Observer* observer) override {
observers.erase(
std::remove(observers.begin(), observers.end(), observer),
observers.end());
}
void notify(const std::string& message) override {
for (Observer* observer : observers) {
observer->update(message);
}
}
};
int main() {
// 创建被观察者
ConcreteSubject subject;
// 创建观察者
ConcreteObserver observer1("Observer 1");
ConcreteObserver observer2("Observer 2");
// 订阅观察者
subject.subscribe(&observer1);
subject.subscribe(&observer2);
// 发送通知
subject.notify("Hello, Observers!");
// 取消订阅观察者1
subject.unsubscribe(&observer1);
// 再次发送通知
subject.notify("Second notification");
return 0;
}
3.观察者模式的优点
-
观察者与被观察者之间是抽象耦合
如此设计,则不管是增加观察者还是被观察者都非常容易扩展
-
建立一套触发机制
4.缺点
- 需要考虑一下开发效率和运行效率的问题,一个被观察者,多个观察者,开发和调试就会比较复杂。如果是顺序执行,一个观察者卡壳,会影响整体效率,在这种情况下,一般采用异步方式。
- 多级触发时的效率可能更不太好
5.使用场景
- 关联行为场景。关联行为是可拆分的,而不是组合关系
- 事件多级触发场景
- 跨系统的消息交换场景,如消息队列的处理机制
注意事项
-
个观察者可以有双重身份,既是观察者,也是被观察者,但是链一旦建立,这个逻辑就比较复杂,可维护性非常差,根据经验建议,在一个观察者模式中最多出现一个对象既是观察者也是被观察者,也就是说消息最多转发一次(传递两次)
-
异步处理问题
被观察者发生动作了,观察者要做出回应,如果观察者比较多,就用异步处理,要考虑线程安全和队列的问题
它和责任链模式的最大区别就是观察者广播链在传播的过程中消息是随时更改 的,它是由相邻的两个节点协商的消息结构;而责任链模式在消息传递过程中基本上保持消 息不可变,如果要改变,也只是在原有的消息上进行修正
项目中的实际用法
1.观察者和被观察者之间的消息沟通
被观察者状态改变会触发观察者的一个行为,同时会传递一个消息给观察者
2.观察者响应方式
如果观察者是一个比较复杂的逻辑,它要接受被观察者传递过来的 信息,同时还要对他们进行逻辑处理,在一个观察者多个被观察者的情况下,就需要考虑性能需求了。两个办法:
- 多线程
- 缓存技术
3.观察者尽量自己做主
被观察者的状态改变是否一定要通知观察者呢?不一定
一般这样做,对被观察者的业务逻辑 doSomething方法实现重载,如增加一个doSomething(boolean isNotifyObs)方法,决定是否通知观察者,而不是在消息到达观察者时才判断