观察者设计模式是最简单的行为型模式之一;行为型模式,它主要关注的是对象的责任。它们用来处理对象之间的交互,以实现更大的功能。行为型模式建议:对象之间应该能够彼此交互,同时还应该是松散耦合的。
理解观察者设计模式
在观察者设计模式中,对象(主题)维护了一个依赖(观察者)列表,以便主题可以使用观察者定义的任何方法通知所有观察者它所发生的变化。
在分布式应用的世界中,多个服务通常是通过彼此交互来实现用户想要实现的更大型的操作。服务可以执行多种操作,但是他们执行的操作会直接或很大程度上取决于与其交互的服务对象的状态。
观察者模式的主要目标如下:
1、它定义了对象之间一对多的依赖关系,从而使一个对象中的任何更改都将自动通知给其它依赖对象
2、他封装了主题的核心组件
观察者模式的应用场景:
1、在分布式系统中实现事件服务
2、用作新闻机构的框架
3、股票市场也是观察者模式的一个大型场景
Python代码的实现:
class Subject(object):
def __init__(self):
self.__observer = []
def register(self, observer):
self.__observer.append(observer)
def notify_all(self, *args, **kwargs):
for observer in self.__observer:
observer.notify(self, *args, **kwargs)
class Observer1(object):
def __init__(self, subject):
subject.register(self)
def notify(self, subject, *args):
print(type(self).__name__, 'Got', args, 'From', subject)
class Observer2(object):
def __init__(self, subject):
subject.register(self)
def notify(self, subject, *args):
print(type(self).__name__, 'Got', args, 'From', subject)
subject = Subject()
observer1 = Observer1(subject)
observer2 = Observer2(subject)
subject.notify_all('notification')
观察者模式三个主要角色:
1、主题(Subject):类Subject需要了解Observer。Subject类具有许多的方法,例如register()等,Observer可以通过这些方法注册到Subject类中。因此,一个Subject可以处理多个Observe。
2、观察者(Observer):它为关注主题的对象定义了一个接口。它定义了Observer需要实现的各个方法,以便主题发生变化时能够获得相应的通知;
3、具体观察者(ConcreteObserver):它用来保存应该与Subject的状态保持一致的状态。它实现了Observer接口以保持其状态与主题中的变化相一致。
这个流程非常简单。具体观察者通过实现观察者提供的接口向主题注册自己。每当状态发生变化时,该主题都会使用观察者提供的通知方法来通告所有具体观察者。
生活中的观察者模式
我们将以新闻机构为例来展示观察者模式的生活中的场景。新闻机构通常从不同地点收集新闻,并将其发布给订阅者。下面利用Python来开发一个应用程序,实现上面的用例。
从主题开始,这里的主题是新闻发布者:
1、主题的行为有NewsPublisher类表示
2、NewsPublisher提供了一个订阅用户使用的接口
3、attach()方法供观察者(Observer)来注册NewsPublisherObserver,detach()方法用于注销
4、subscriber()方法返回已经使用Subject注册所有订阅用户列表
5、notify_subscriber()方法可以用来遍历已向NewsPublisher注册的所有订阅用户
6、发布者可以使用add_news()方法创建新的消息,get_news()用于返回最新消息,并且通知观察者。
class NewsPublisher(object):
def __init__(self):
self.__subscribers = []
self.__latest_news = None
def attach(self, subscriber):
self.__subscribers.append(subscriber)
def detach(self):
return self.__subscribers.pop()
def subscribers(self):
return [type(x).__name__ for x in self.__subscribers]
def notify_subscribers(self):
for sub in self.__subscribers:
sub.update()
def add_news(self, news):
self.__latest_news = news
def get_news(self):
return "Got News:", self.__latest_news
现在我们讨论观察者(Observer)接口:
1、在这个例子中,Subscriber表示Observer,它是一个抽象的基类,代表其他ConcreteObserver;
2、Subscriber有一个update()方法,但是它需要由ConcreteObservers实现
3、update()方法是由ConcreteObserver实现的,这样只要有新闻发布时,它们都能够得到Subject的相应通知
from abc import ABCMeta, abstractmethod
class Subscriber(object):
@abstractmethod
def update(self):
pass
下面试具体观察者:
1、在本例中,我们有两个主要观察者,分别实现订阅用户接口的EmailSubscriber和SMSSubscriber
2、除了这两个外,我们建立了另外一个观察者AnyOtherObserver,它是用来演示Observers与Subject的松散耦合关系的
3、每个具体观察者的__init__()方法都是使用attach()方法向NewsPublisher进行注册
4、具体观察者的update()方法由NewsPublisher在内部用来通知添加新的新闻
class SMSSubscriber(object):
def __init__(self, publisher):
self.publisher = publisher
self.publisher.attach(self)
def update(self):
print(type(self).__name__, self.publisher.get_news())
class EmailSubscriber(object):
def __init__(self, publisher):
self.publisher = publisher
self.publisher.attach(self)
def update(self):
print(type(self).__name__, self.publisher.get_news())
class AnyOtherSubscriber(object):
def __init__(self, publisher):
self.publisher = publisher
self.publisher.attach(self)
def update(self):
print(type(self).__name__, self.publisher.get_news())
以下代码展示主题和观察者之间的交互:
if __name__ == "__main__":
news_publisher = NewsPublisher()
for Subscribers in [SMSSubscriber, EmailSubscriber, AnyOtherSubscriber]:
Subscribers(news_publisher)
print("\nSubscribers:", news_publisher.subscribers())
news_publisher.add_news("地球爆炸了")
news_publisher.notify_subscribers()
print("\nDetached:", type(news_publisher.detach()).__name__)
print("\nSubscribers:", news_publisher.subscribers())
news_publisher.add_news("二二二二二")
news_publisher.notify_subscribers()