观察者模式应用比较广泛,又被称为“发布-订阅”模式。它用来定义对象间一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都得到通知并被自动更新。
出于安全与调用者方便的原因
1.由于为了隐藏发布者消息被篡改,所以设置成立私有属性__
2.设置私有属性后,就必须单独写一个函数来调用,一个属性却需要使用函数的调用方式,会让调用者迷惑。要使用"@property"装饰器语法
3.这个属性,有时会需要调用者重新赋值,要使用"@*.setter"装饰器语法
以上的内容也是为了演示,在订阅者名单中,删除某订阅者名字后,某订阅者会不会收到新消息。
from abc import ABCMeta, abstractmethod
# 抽象的订阅者
class Observer(metaclass=ABCMeta):
@abstractmethod
def update(self, notice):
pass
# 抽象的发布者:可以是接口,子类不需要实现,所以不需要定义抽象方法!
class Notice:
def __init__(self):
self.observers = []
def attach(self, obs):
# 添加 订阅者名单
self.observers.append(obs)
def detach(self, obs):
# 删除 订阅者名单
self.observers.remove(obs)
def notify(self):
# 遍历订阅者名单
for obs in self.observers:
# 使用订阅者的方法,把发布者作为参数输入
obs.update(self)
# 具体的发布者
class StaffNotice(Notice):
def __init__(self, company_info):
super().__init__() # 调用父类对象声明observers属性
# 设置了私有属性
self.__company_info = company_info
# @property 与 @*.setter 可以配合使用
# 既要保护类的封装特性,又要让开发者可以使用“对象.属性”的方式操作操作类属性,
# 通过 @property 装饰器,可以直接通过方法名来访问方法,不需要在方法名后添加一对“()”小括号。
@property
def company_info(self):
# 直接返回 __company_info
return self.__company_info
# 两个同名函数, 当company_info这个"属性"被赋值时,该函数会被执行 (预处理)
@company_info.setter
def company_info(self, info):
# 更新 __company_info
self.__company_info = info
# 调用发布者的方法
self.notify()
# 具体的订阅者
class Staff(Observer):
def __init__(self):
self.company_info = None
def update(self, notice):
# 输入参数.调用发布者的方法 赋值给 订阅者(自己)
self.company_info = notice.company_info
# 实例化 发布者
staff_notice = StaffNotice('初始化公司信息')
# 实例化 订阅者
staff1 = Staff()
staff2 = Staff()
# 添加订阅
staff_notice.attach(staff1)
staff_notice.attach(staff2)
# print(staff1.company_info) None
# print(staff2.company_info) None
# 当company_info这个"属性"被赋值时, 会触发"预处理"
# 订阅者 会接收 发布者 的消息
staff_notice.company_info = '假期放假通知!'
print(staff1.company_info)
print(staff2.company_info)
# 删除 订阅者 staff2
staff_notice.detach(staff2)
# 重新 发布订阅
staff_notice.company_info = '明天开会!'
# staff1 会接收到新的消息
print(staff1.company_info)
# staff2 不会接收到新的消息
print(staff2.company_info)
"""
假期放假通知!
假期放假通知!
明天开会!
假期放假通知!
"""