观察者模式是一种设计模式,它允许一个对象或者事件,将消息发送给一组正在观察(订阅)它们的对象。这种模式的核心在于,发布者和订阅者之间的解耦。本篇文章将会从多个角度分析观察者模式,以便更好的理解。
实现
先来看一个观察者模式的例子。假设有一个主题类,持有一组观察者,当主题状态发生变化时,就会将状态通知给所有观察者。
```python
class Subject:
def __init__(self):
self.observers = []
self.value = None
def register_observer(self, observer):
self.observers.append(observer)
def remove_observer(self, observer):
self.observers.remove(observer)
def notify_observers(self):
for observer in self.observers:
observer.update(self.value)
def set_value(self, value):
self.value = value
self.notify_observers()
class Observer:
def update(self, value):
pass
class ConcreteObserver(Observer):
def __init__(self, name):
self.name = name
def update(self, value):
print("{} received update with value {}".format(self.name, value))
```
这里的 Subject 是主题类,持有一个观察者列表 observers,当 set_value 方法被调用时,会将 value 变量的值更新,并将这个变化通知给所有观察者。Observer 是观察者接口,ConcreteObserver 是观察者的具体实现。
现在可以进行测试。
```python
def test_observer():
subject = Subject()
observer_a = ConcreteObserver("observer a")
observer_b = ConcreteObserver("observer b")
subject.register_observer(observer_a)
subject.register_observer(observer_b)
subject.set_value("hello")
subject.remove_observer(observer_a)
subject.set_value("world")
```
执行结果:
```
observer a received update with value hello
observer b received update with value hello
observer b received update with value world
```
角色分析
在上面的例子中,观察者模式的两个主要角色是主题(Subject)和观察者(Observer)。Subject 持有了一组观察者,通过注册和删除观察者的方式,来维护观察者列表。当状态发生变化时,Subject 会遍历观察者列表,并将变化通知给所有观察者。
观察者(Observer)是一个接口,所有具体的观察者都要实现这个接口。这个接口只有一个方法 update,当主题状态发生变化时,Subject 会调用观察者的 update 方法,通知它们状态变化了。
优缺点分析
优点:
1.观察者模式可以实现对象之间的解耦,当一个对象发生变化时,不用关心其他模块的影响;
2.主题和观察者的关系是动态的,可以在运行时添加、删除观察者,灵活性非常高;
3.观察者模式符合"开闭原则",增加新的主题或观察者类,不需要修改原有代码。
缺点:
1.如果观察者过多,主题通知它们的操作会变得很慢;
2.Subject 与 Observer 的接口需要一致,不能很好地支持异构以及事件有多个参数的情况;
3.观察者模式下,主题状态转换频繁,相应的观察者也会跟着频繁变动,容易出错。
使用场景
通常可以用观察者模式来实现以下场景:
1.一个对象的状态变化会影响其他对象;
2.当一个对象的改变需要同时改变其他对象的状态时,比如模型-视图系统;
3.当一个非确定的事件或者可更新的状态发生并且需要通知其他对象时。
一些应用
Python 中给了我们很多轮子,也可以体现出观察者模式的应用。
1.Qt 里的信号和槽,其实也就是实现了观察者模式,信号是主题,槽函数是观察者。
2.django 和 flask 中的信号机制,基本就是观察者模式的应用。比如 django 中就有 request_started 和 request_finished 信号,可以让其他响应处理模块接收并处理它们。
结论
在实际开发中,观察者模式的应用非常广泛,比如 MVC 架构,Qt 的事件处理等等。通过本文的分析,我们可以了解到观察者模式的实现、优缺点以及它的使用场景。借此机会,我们也可以学习一些主流框架中的观察者模式的应用,更好地理解和掌握它的使用。
扫码咨询 领取资料