Python观察者模式与发布/订阅模式的区别与联系

2023-04-04 00:00:00 模式 观察者 区别

观察者模式和发布/订阅模式都是软件设计模式中用于实现组件之间松耦合的方法。它们都允许一个对象(被观察者或者发布者)与多个其他对象(观察者或者订阅者)进行通信,但是它们的实现方式和应用场景略有不同。

观察者模式:
观察者模式是一种在对象之间定义一对多的依赖关系,当一个对象的状态发生改变时,它会通知所有依赖它的对象,使得它们能够自动更新自己。观察者模式的核心思想是,一个对象(被观察者)维护一个观察者列表,当对象的状态发生改变时,它会遍历观察者列表并调用它们的方法以通知它们状态变化的消息。

观察者模式的优点是它能够让对象之间的耦合度降低,被观察者不需要知道观察者的具体实现,只需要通知它们即可。这种方式允许我们更加灵活地添加或删除观察者,也使得被观察者对象可以同时通知多个观察者。

下面是一个使用Python实现观察者模式的例子,我们假设有一个名为“Subject”的被观察者类,它维护了一个观察者列表,当状态发生改变时通知所有的观察者:

class Subject:
    def __init__(self):
        self.observers = []

    def add_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)

    def set_state(self, state):
        self.state = state
        self.notify_observers()


class Observer:
    def update(self, subject):
        pass


class ConcreteObserverA(Observer):
    def update(self, subject):
        print(f"ConcreteObserverA received notification: {subject.state}")


class ConcreteObserverB(Observer):
    def update(self, subject):
        print(f"ConcreteObserverB received notification: {subject.state}")


subject = Subject()
observer_a = ConcreteObserverA()
observer_b = ConcreteObserverB()
subject.add_observer(observer_a)
subject.add_observer(observer_b)

subject.set_state("pidancode.com")
subject.set_state("皮蛋编程")

subject.remove_observer(observer_a)
subject.set_state("pidancode.com")

在上面的例子中,我们创建了一个名为Subject的被观察者类,并定义了一个Observer基类和两个具体的Observer实现(ConcreteObserverA和ConcreteObserverB)。当被观察者的状态发生变化时,它会调用notify_observers方法,通知所有的观察者,并且观察者会根据被观察者传递的状态来更新自己的状态。

发布/订阅模式:
发布/订阅模式是一种将消息发布者和订阅者解耦的设计模式。在该模式中,发布者将消息发布到一个主题(或者称为“消息队列”)中,而订阅者则可以订阅这个主题并接收发布者发布的消息。发布者和订阅者之间没有直接的通信,它们之间的交互是通过主题来完成的。

与观察者模式不同的是,发布/订阅模式中的订阅者不需要知道消息的来源(也就是发布者)。订阅者只需要订阅它们感兴趣的主题,然后接收发布者发布的消息即可。这使得发布/订阅模式比观察者模式更加灵活和可扩展,因为发布者和订阅者之间没有直接的依赖关系。

下面是一个使用Python实现发布/订阅模式的例子,我们假设有一个名为“MessageBroker”的消息代理类,它维护了一个主题列表和相应的订阅者列表,当有新的消息发布时,它会通知所有订阅该主题的订阅者:

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

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

    def unsubscribe(self, topic, subscriber):
        if topic in self.topics:
            self.topics[topic].remove(subscriber)

    def publish(self, topic, message):
        if topic in self.topics:
            for subscriber in self.topics[topic]:
                subscriber.receive(message)


class Subscriber:
    def receive(self, message):
        pass


class ConcreteSubscriberA(Subscriber):
    def receive(self, message):
        print(f"ConcreteSubscriberA received message: {message}")


class ConcreteSubscriberB(Subscriber):
    def receive(self, message):
        print(f"ConcreteSubscriberB received message: {message}")


broker = MessageBroker()
subscriber_a = ConcreteSubscriberA()
subscriber_b = ConcreteSubscriberB()

broker.subscribe("pidancode.com", subscriber_a)
broker.subscribe("皮蛋编程", subscriber_a)
broker.subscribe("pidancode.com", subscriber_b)

broker.publish("pidancode.com", "New article published")
broker.publish("皮蛋编程", "New tutorial released")

broker.unsubscribe("pidancode.com", subscriber_a)

broker.publish("pidancode.com", "New feature released")

在上面的例子中,我们创建了一个名为MessageBroker的消息代理类,并定义了一个Subscriber基类和两个具体的Subscriber实现(ConcreteSubscriberA和ConcreteSubscriberB)。当订阅者订阅某个主题时,它会将自己添加到主题对应的订阅者列表中。当发布者发布消息时,消息代理会将消息发布到对应主题的订阅者列表中,然后订阅者将接收到消息并做出相应的处理。

在上面的例子中,我们假设有两个订阅者订阅了“pidancode.com”主题,一个订阅者订阅了“皮蛋编程”主题。当发布者发布一条新消息时,所有订阅了该主题的订阅者都会收到这条消息。

需要注意的是,观察者模式和发布/订阅模式并不是互斥的,它们可以一起使用来构建更复杂的系统。例如,在一个大型的分布式系统中,我们可以使用发布/订阅模式来进行不同节点之间的消息传递,而在每个节点内部,我们可以使用观察者模式来处理节点内部状态的更新。

总结一下,观察者模式和发布/订阅模式都是用来解耦发布者和订阅者的设计模式。观察者模式中,发布者和订阅者之间存在直接的依赖关系,而发布/订阅模式中则没有。观察者模式中,订阅者需要知道发布者的存在,而发布/订阅模式中,订阅者只需要订阅感兴趣的主题即可。两种模式都有自己的优缺点,我们需要根据具体的应用场景来选择合适的模式来解决问题。

相关文章