📜  在Python中使用观察者设计模式实现时事通讯订阅

📅  最后修改于: 2022-05-13 01:54:53.937000             🧑  作者: Mango

在Python中使用观察者设计模式实现时事通讯订阅

观察者设计模式是Python中的一种设计模式,可促进一对多关系。例如,假设您和其他几位读者订阅了一份时事通讯。当有新的时事通讯可用时,您将与其他订阅者一起收到它。假设,如果您不想收到时事通讯,您可以取消订阅,并且不会收到新版本。

观察者设计模式不限于时事通讯订阅。它可以是任何信息,例如并发线程信号、来自操作系统的信号等。观察者设计模式是发布订阅者模式的一种形式。它有助于管理订阅和向订阅者广播信息。

观察者设计模式的好处

观察者设计模式有一个名为 Subject 的静态对象和一个名为 Observers 的可变对象。可以有零个或 N 个观察者,这可以根据订阅而改变。在这里,主体保留观察者,如果任何对象状态发生变化,主体会通知其他观察者。例如,考虑 LinkedIn 帖子的情况。当您发布新的 LinkedIn 帖子(状态更改)时,您的关注者的时间线会随着您的新帖子更新。

让我们来看看它的好处。

  • 促进主题和观察者之间的松散耦合
  • 观察者可以在运行时更新
  • 一个主题可以保留零个或 N 个观察者
  • 在 Subject 和 Observers 之间广播消息的能力。

通讯订阅实施

让我们设计一个简单的时事通讯订阅模型来理解观察者设计模式。正如我们所讨论的,观察者设计模式有两个主要对象——主题和观察者。主体可以通过 register_observer、unregister_observer 和 notify_observer 添加、删除和通知观察者。而观察者是一个接口,它有一个抽象方法——notify。

观察者设计模式

在这里,两个具体的观察者——CompanyNewsletterObserver 和 ConsumerNewsletterObserver——派生自 Observer 接口。这些具体的方法实现了抽象方法notify,Subject 会在它的notify_observer 方法中调用notify 方法。所以要向订阅者发送信息,我们只需要调用Subject 中的notify_observer 方法。让我们来看看实现。

Python3
import abc
import time
import datetime
  
class Subject(object):
    def __init__(self):
        self.observers = []
        self.cur_time = None
  
    def register_observer(self, observer):
        if observer in self.observers:
            print(observer, 'already registered')
        else:
            self.observers.append(observer)
  
    def unregister_observer(self, observer):
        try:
            self.observers.remove(observer)
        except ValueError:
            print('Cannot Indentify the Observer')
  
    def notify_observer(self):
        self.cur_time = datetime.datetime.now()
          
        for observer in self.observers:
            observer.notify(self.cur_time)
  
class Observer(object, metaclass=abc.ABCMeta):    
    """ Abstract class for Observers """
    @abc.abstractmethod
    def notify(self, unix_timestamp):
        pass
  
  
class CompanyNewsletterObserver(Observer):
    """ Company Newsletter """
    def __init__(self, name):
        self.name = name
  
    def notify(self, time):
        print(self.name, ':', time)
  
class ConsumerNewsletterObserver(Observer):
    """ Consumer Newsletter """
    def __init__(self, name):
        self.name = name
  
    def notify(self, time):
        print(self.name, ':', time)
  
if __name__ == '__main__':
    subject = Subject()
  
    print('Registering company_newsletter_observer')
    cmp_observer = CompanyNewsletterObserver('company_newsletter_observer')
    subject.register_observer(cmp_observer)
    subject.notify_observer()
    print()
    time.sleep(2)
  
    print('Registering consumer_newsletter_observer')
    con_observer = ConsumerNewsletterObserver('consumer_newsletter_observer')
    subject.register_observer(con_observer)
    subject.notify_observer()
    print()
    time.sleep(2)
  
    print('Unregistering company_newsletter_observer')
    subject.unregister_observer(cmp_observer)
    subject.notify_observer()


输出:

您可以参考上面的输出来了解注册和取消注册观察者时代码的行为。

观察者设计模式最适合实现一对多关系的需要。您可以向许多听众广播相同的信息。并且,可以在运行时添加或删除侦听器。在这里,主体只有关于观察者接口的信息,这有助于保持主体和观察者之间的松散耦合。