在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()
输出:
Registering company_newsletter_observer
company_newsletter_observer : 2020-10-15 20:40:04.335355
Registering consumer_newsletter_observer
company_newsletter_observer : 2020-10-15 20:40:06.336913
consumer_newsletter_observer : 2020-10-15 20:40:06.336913
Unregistering company_newsletter_observer
consumer_newsletter_observer : 2020-10-15 20:40:08.339662
您可以参考上面的输出来了解注册和取消注册观察者时代码的行为。
观察者设计模式最适合实现一对多关系的需要。您可以向许多听众广播相同的信息。并且,可以在运行时添加或删除侦听器。在这里,主体只有关于观察者接口的信息,这有助于保持主体和观察者之间的松散耦合。