Python设计模式之观察者模式丨【生长吧!Python】
1、什么是观察者模式
在对象间定义一种一对多的依赖关系,当这个对象状态发生改变时,所有依赖它的对象都会被通知并自动更新。观察者模式是一种一对多的关系,可以有任意个(一个或多个)观察者对象同时监听某一个对象。监听的对象叫观察者,被监听的对象叫被观察者(Observable,也叫主题,即Subject)。被观察者对象在状态或内容(数据)发生变化时,会通知所有观察者对象,使它们能够做出相应的变化(如自动更新自己的信息)。
2、观察者模式设计思想
观察者模式,顾名思义就是观察与被观察的关系。观察者模式是对象的行为模式,又叫发布/订阅(Publish/Subscribe)模式、模型/视图(Model/View)模式、源/监听器(Source/Listener)模式或从属者(Dependents)模式。当你看这些模式的时候,不要觉得陌生,它们就是观察者模式。观察者的核心思想就是在被观察者与观察者之间建立一种自动触发的关系。
3、观察者模式的模型抽象
3.1、代码框架
from abc import ABCMeta, abstractmethod
# 引入ABCMeta 和 abstractmethod来定义抽象类和抽象方法
class Observer(metaclass=ABCMeta):
"""观察者的基类"""
@abstractmethod
def update(self, observable, object):
pass
class Observable:
"""被观察者的基类"""
def __init__(self):
self.__observers = []
def addObserver(self, observer):
self.__observers.append(observer)
def removeObserver(self, observer):
self.__observers.remove(observer)
def notifyObservers(self, object=0):
for o in self.__observers:
o.update(self, object)
3.2、类图
Observable是被观察者的抽象类,Observer是观察者的抽象类。addObserver、removeObserver分别用于添加和删除观察者,notifyObservers 用于内容或状态变化时通知所有的观察者。因为Observable的notifyObservers会调用Observer的update方法,所有观察者不需要关心被观察的对象什么时候会发生变化,只要有变化就会自动调用update,所以只需要关注update实现就可以了。
3.3、模型说明
1、设计要点
(1)要明确谁是观察者谁是被观察者。一般观察者与被观察者之间是多对一的关系,一个被观察对象可以有多个观察者。
(2)Observable 在发送广播通知的时候,无须指定具体的 Observer,Observer可以自己决定是否订阅Subject的通知。
(3)被观察者至少需要有三个方法:添加监听者、移除监听者、通知Observer的方法。观察者至少要有一个方法:更新方法,即更新当前的内容,做出相应的处理。
(4)添加观察者和移除观察者在不同的模型称谓中可能会有不同命名,如在观察者模型中一般是addObserver/removeObserver;在源/监听器(Source/Listener)模型中一般是attach/detach,应用在桌面编程的窗口中还可能是attachWindow/detachWindow或Register/UnRegister。不要被名称弄迷糊了,不管它们是什么名称,其实功能都是一样的,就是添加或删除观察者。
2、推模型和拉模型
监听模式根据其侧重的功能还可以分为推模型和拉模型。
推模型:
被观察者对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。一般在这种模型的实现中,会把被观察者对象中的全部或部分信息通过update参数传递给观察者(update(Object obj),通过obj参数传递)。
拉模型:
被观察者在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到被观察者对象中获取,相当于观察者从被观察者对象中拉数据。一般在这种模型的实现中,会把被观察者对象自身通过 update 方法传递给观察者(update(Observable observable),通过observable 参数传递),这样在观察者需要获取数据的时候,就可以通过这个引用来获取了。
3、总结说明
推模型和拉模型其实更多的是语义和逻辑上的区别。我们前面的代码框架,从接口[update(self,observer,object)]上你应该可以知道是同时支持推模型和拉模型的。作为推模型时,observer可以传空,推送的信息全部通过object传递;作为拉模型时,observer和object都传递数据,或只传递observer,需要更具体的信息时通过observer引用去取数据。
4、应用场景
(1)对一个对象状态或数据的更新需要其他对象同步更新,或者一个对象的更新需要依赖另一个对象的更新。
(2)对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节,如消息推送。
【生长吧!Python】有奖征文火热进行中:https://bbs.huaweicloud.com/blogs/278897
- 点赞
- 收藏
- 关注作者
评论(0)