面试大揭秘:发布订阅与观察者模式的区别

社区

---theme: theme-orange --- ​

再前面两章,我们分别学习了发布订阅观察者模式。恰巧最近再面试的过程中遇到了相关问题,于是在我略施拳脚后成功**说服(shuì fú)**了面试官。

面试现场

🙎🏻‍♀️ HR小姐姐: 你是来参加面试的吧?

🤵🏻 我: 是的,我昂起头,自信地点了点头。

🙎🏻‍♀️ HR小姐姐: 面试官马上就来,我先带你去会议室。

会议室

🙎🏻‍♀️ HR小姐姐: 面试官临时有个会议,你稍等一会儿。

👨🏻‍💼 面试官走进来:你是杰克马是吧?

🤵🏻 我: 你好,面试管。我叫马杰克,那名字可不敢叫,那不是僭越了嘛。

👨🏻‍💼 面试官: 你小子,还是有分寸的,我们开始面试,你简单介绍一下自己。

🤵🏻 我: 好的,我开始自信地介绍自己。

👨🏻‍💼 面试官: 挑一个你最熟悉的技能说说。

🤵🏻 我: (PS:你小子这不是踢钢板上了么)我最近正在阅读《Head First 设计模式》,想谈谈设计模式。

👨🏻‍💼 面试官: 那你说说观察者模式和发布订阅模式的区别吧。

于是就有了下面的内容

理解概念

发布订阅(Publish-Subscribe)和观察者(Observer)模式都是设计模式中常用的通信模式,用于实现对象间的解耦和事件处理。

  • 发布订阅模式:在这种模式中,发布者和订阅者之间没有直接依赖关系。它们通过一个中介(消息代理或事件总线)进行通信。发布者发布消息到消息代理,订阅者从消息代理订阅消息。这样,发布者和订阅者不需要知道对方的存在。
  • 观察者模式:在这种模式中,观察者和被观察者(也叫主题)之间存在直接依赖关系。观察者注册自己感兴趣的主题,然后等待主题的通知。主题维护一个观察者列表,当状态改变时,主题会通知列表中的观察者。

这种概念的性的描述不利于记忆,我们举个例子说明一下,我有一个朋友叫英俊,他酷爱洗澡。

发布订阅模式

  • 场景描述:洗浴中心通过合作饭店进行促销活动,饭店的顾客在满足一定条件下可以以优惠价格购买洗浴中心的年卡。洗浴中心通过这种方式吸引新客户,并通过客户的口碑传播进一步增加客户基数。

在这个例子中,洗浴中心可以视为“发布者”,而饭店的顾客可以视为“订阅者”。洗浴中心发布优惠信息(发布),饭店的顾客通过饭店得知优惠信息并选择购买(订阅)。这种模式实现了洗浴中心和顾客之间的解耦,洗浴中心不需要直接与每个顾客沟通,而是通过饭店这个中介来发布信息。

观察者模式

  • 场景描述:洗浴中心通过观察顾客的使用频率和偏好,来调整服务和营销策略。例如,如果某个顾客经常来洗浴中心,洗浴中心可能会针对这位顾客提供个性化的服务或优惠。

在这个例子中,洗浴中心可以视为“被观察者”,而顾客可以视为“观察者”。洗浴中心通过观察顾客的行为(使用频率和偏好)来调整自己的服务策略,而顾客则通过自己的行为影响洗浴中心的服务提供。这种模式实现了洗浴中心和顾客之间的紧密互动,但保持了各自的独立性。

如果还没懂,这边建议您先去洗个澡,清醒一下。

结构对比

发布订阅模式(Publish-Subscribe)

  1. 参与者:包括发布者(Publisher)、订阅者(Subscriber)和消息代理(Message Broker)。
  2. 结构:发布者和订阅者通过消息代理进行通信,发布者将消息发送到消息代理,消息代理将消息分发给订阅者。
  3. 解耦:发布者和订阅者之间完全解耦,彼此不知道对方的存在,只需通过消息代理进行消息传递。
  4. 使用场景:适用于系统中有大量松散耦合的组件,需要进行复杂的事件传递和处理,例如事件驱动系统、日志收集、通知系统等。
  5. 实现方式:通常通过消息队列(如RabbitMQ、Kafka)或事件总线(如EventBus)来实现。

观察者模式(Observer)

  1. 参与者:包括被观察者(Subject)和观察者(Observer)。
  2. 结构:被观察者维护一个观察者列表,当被观察者状态发生变化时,通知所有观察者。
  3. 耦合度:观察者和被观察者之间存在一定的耦合,观察者需要注册到被观察者中,被观察者知道观察者的存在。
  4. 使用场景:适用于一个对象状态变化需要通知多个对象的场景,例如GUI应用中的事件监听、数据模型与视图同步等。
  5. 实现方式:通常通过直接的对象引用和方法调用来实现,比较简单。

picture.image

对比总结

特性发布订阅模式观察者模式
参与者发布者、订阅者、消息代理被观察者、观察者
结构通过消息代理进行消息传递被观察者直接通知观察者
解耦程度发布者和订阅者完全解耦被观察者和观察者之间有一定耦合
通信方式异步(通过消息队列或事件总线)同步(通过方法调用)
使用场景事件驱动系统、大规模分布式系统GUI事件监听、模型视图同步等小规模系统
实现复杂度较高,需要引入消息代理或事件总线较低,通过对象引用和方法调用实现
示例代码

发布订阅模式

class MessageBroker:
    def __init__(self):
        self.subscribers = {}

    def subscribe(self, event_type, subscriber):
        if event_type not in self.subscribers:
            self.subscribers[event_type] = []
        self.subscribers[event_type].append(subscriber)

    def publish(self, event_type, data):
        if event_type in self.subscribers:
            for subscriber in self.subscribers[event_type]:
                subscriber.update(data)

class Subscriber:
    def update(self, data):
        print(f"Received data: {data}")

broker = MessageBroker()
subscriber = Subscriber()

broker.subscribe("event", subscriber)
broker.publish("event", "Hello, World!")

picture.image

观察者模式

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, data):
        for observer in self.observers:
            observer.update(data)

class Observer:
    def update(self, data):
        print(f"Observer received data: {data}")

subject = Subject()
observer = Observer()

subject.attach(observer)
subject.notify("Hello, World!")

picture.image

日常生活示例

发布订阅模式

报纸订阅

  1. 发布者:报社
  2. 订阅者:读者
  3. 消息代理:邮局

过程

  • 读者(订阅者)通过邮局(消息代理)订阅了某个报社(发布者)的报纸。
  • 每天,报社会把最新的报纸送到邮局。
  • 邮局根据订阅信息,将报纸分发给所有订阅的读者。

报社并不知道具体有谁订阅了报纸,它只负责把报纸交给邮局,邮局负责管理订阅信息和分发报纸。读者和报社之间没有直接联系,它们通过邮局进行通信。

观察者模式

班主任和学生

  1. 被观察者:班主任
  2. 观察者:学生

过程

  • 班主任(被观察者)在班级中宣布了一条重要通知。
  • 每个学生(观察者)都在听班主任的通知。
  • 班主任说完通知后,所有学生都收到了这条通知。

班主任知道哪些学生在听通知,并且直接将通知传达给他们。学生和班主任之间有直接的联系,学生需要注册到班主任的通知列表中才能接收通知。

picture.image

对比总结

  • 发布订阅模式(报纸订阅):报社(发布者)和读者(订阅者)之间完全解耦,通过邮局(消息代理)进行通信。
  • 观察者模式(班主任和学生):班主任(被观察者)直接通知学生(观察者),彼此之间有直接联系。
最后

👨🏻‍💼 面试官: 你对观察者模式和发布订阅模式的理解非常的透彻,整的表现也非常的出色,后续HR会与你联系,回去等结果通知

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论