返回
订发布与观察者模式,一篇文章掌握二者区别
前端
2023-09-25 13:28:13
订阅发布模式和观察者模式:用于对象通信的强大模式
订阅发布模式(Pub/Sub) 和观察者模式 是软件设计中用于实现对象之间通信的两种强大的模式。它们拥有许多相似之处,但也有一些关键的区别。
订阅发布模式
想象一下一个繁忙的街道,有许多行人。订阅发布模式就像交通信号灯。当一个行人(发布者)按下按钮时,信号灯(主题或代理)就会将一条消息(信号更改)发送给所有感兴趣的行人(订阅者)。
特点:
- 可扩展性: 易于添加或删除订阅者,提高了系统的灵活性。
- 松耦合: 发布者和订阅者之间没有直接依赖关系,使系统更易于维护和扩展。
- 高性能: 消息通过队列或主题传递,避免了阻塞。
缺点:
- 调试困难: 跟踪消息流向可能很困难,影响了可调试性。
- 消息丢失: 如果订阅者在消息发送时宕机,可能会丢失消息。
示例代码:
import asyncio
# 创建一个主题(消息代理)
topic = asyncio.Queue()
# 创建订阅者
async def subscriber(topic):
while True:
message = await topic.get()
print(f"Subscriber received: {message}")
# 创建发布者
async def publisher(topic):
await topic.put("Hello, world!")
# 运行事件循环
asyncio.run(publisher(topic))
asyncio.run(subscriber(topic))
观察者模式
现在,想象一个教室里有一群学生(观察者)。老师(被观察者)一直在监控学生的活动。当老师注意到一名学生举手(状态更改)时,他/她会通知所有学生(观察者),例如:“约翰有疑问。”
特点:
- 易于实现: 易于理解和实现,代码相对简单。
- 可扩展性: 易于添加或删除观察者,提高了系统的灵活性。
- 松耦合: 被观察者和观察者之间没有直接依赖关系,使系统更易于维护和扩展。
缺点:
- 性能开销: 每次被观察者状态更改时,都需要通知所有观察者,这可能会产生性能开销。
- 维护困难: 当添加或删除观察者时,需要修改被观察者的代码,影响了可维护性。
示例代码:
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self, message):
for observer in self._observers:
observer.update(message)
class Observer:
def __init__(self, subject):
self._subject = subject
self._subject.attach(self)
def update(self, message):
print(f"Observer received: {message}")
# 创建被观察者
subject = Subject()
# 创建观察者
observer1 = Observer(subject)
observer2 = Observer(subject)
# 发送通知
subject.notify("Hello, world!")
共同点
订阅发布模式和观察者模式都用于实现对象之间的通信,并且都具有可扩展性和松耦合性。
区别
特征 | 订阅发布模式 | 观察者模式 |
---|---|---|
发布者/被观察者数量 | 1发布者对多订阅者 | 1被观察者对多观察者 |
消息传递时序性 | 异步,消息通过队列传递 | 同步,被观察者状态更改时立即通知观察者 |
消息传递耦合性 | 松耦合 | 紧耦合 |
应用场景
订阅发布模式:
- 消息队列
- 事件总线
- 松散耦合系统中的通信
观察者模式:
- GUI编程
- 数据绑定
- 状态监控
常见问题解答
1. 订阅发布模式和观察者模式有什么本质区别?
订阅发布模式中的发布者和订阅者没有直接依赖关系,而观察者模式中的被观察者和观察者之间有直接依赖关系。
2. 哪个模式的性能更好?
订阅发布模式通常性能更好,因为消息通过队列或主题传递,而观察者模式需要在每次状态更改时通知所有观察者。
3. 何时使用订阅发布模式?
当需要将消息发送给多个接收者时使用订阅发布模式,例如消息队列或事件总线。
4. 何时使用观察者模式?
当需要让多个对象知道某个对象的状态更改时使用观察者模式,例如GUI编程或数据绑定。
5. 哪个模式更易于实现?
观察者模式通常更易于实现,因为它只需要简单的代码来注册和取消注册观察者。