返回

订发布与观察者模式,一篇文章掌握二者区别

前端

订阅发布模式和观察者模式:用于对象通信的强大模式

订阅发布模式(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. 哪个模式更易于实现?

观察者模式通常更易于实现,因为它只需要简单的代码来注册和取消注册观察者。