设计模式之监听模式
本文将会介绍设计模式中的监听模式
。
监听模式
是一种一对多的关系,可以有任意个(一个或多个)观察者对象同时监听某一个对象。监听的对象叫观察者(Observer),被监听的对象叫作被观察者(Observable)。被观察者对象在状态或内容(数据)发生变化时,会通知所有观察者对象,使它们能够做出相应的变化。
监听模式
又名观察者模式
,顾名思义就是观察与被观察的关系。比如你在烧开水的时候看着它开没开,你就是观察者,水就是被观察者;再比如你在带小孩,你关注他是不是饿了,是不是渴了,是不是撒尿了,你就是观察者,小孩就是被观察者。观察者模式是对象的行为模式,又叫发布/订阅(Publish/Subscribe)模式、模型/视图(Model/View)模式、源/监听器(Source/Listener)模式或从属者(Dependents)模式。
监听模式的核心思想就是在被观察者与观察者之间建立一种自动触发的关系。
例子
以家中常见的热水器为例,需对水温进行监控,当水温在50-70℃时,会发出警告:可以用来洗澡了!当水温在100℃时,会发出警告:可以用来饮水了!在这里洗澡模式和饮用模式扮演了监听的角色,而热水器则是被监听的对象。一旦热水器中的水温度发生变化,监听者就能及时知道并做出相应的判断和动作。
UML类图如下:
Python代码如下:
# -*- coding: utf-8 -*-
from abc import 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)
# 热水器
class WaterHeater(Observable):
def __init__(self):
super().__init__()
self.__temperature = 25
def getTemperature(self):
return self.__temperature
def setTemperature(self, temperature):
self.__temperature = temperature
print(f"当前温度是:{str(self.__temperature)}℃")
self.notifyObservers()
# 洗澡模式
class WashingMode(Observer):
def update(self, observable, object):
if isinstance(observable, WaterHeater) and 50 <= observable.getTemperature() <= 70:
print("水已烧好!温度正好,可以用来洗澡了。")
# 饮用模式
class DrinkingMode(Observer):
def update(self, observable, object):
if isinstance(observable, WaterHeater) and observable.getTemperature() >= 100:
print("水以烧开!可以用来饮用了。")
def testWaterHeater():
heater = WaterHeater()
washingObser = WashingMode()
drinkingObser = DrinkingMode()
heater.addObserver(washingObser)
heater.addObserver(drinkingObser)
heater.setTemperature(40)
heater.setTemperature(60)
heater.setTemperature(100)
if __name__ == '__main__':
testWaterHeater()
输出结果如下:
当前温度是:40℃
当前温度是:60℃
水已烧好!温度正好,可以用来洗澡了。
当前温度是:100℃
水以烧开!可以用来饮用了。
总结
在设计监听模式的程序时需要注意以下几点:
- 要明确谁是观察者谁是被观察者,只要明白谁是应该关注的对象,问题也就明白了。一般观察者与被观察者之间是多对一的关系,一个被观察对象可以有多个监听对象(观察者)。
- Observable在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否订阅Subject的通知。
- 被观察者至少需要有三个方法:添加监听者、移除监听者、通知Observer的方法。观察者至少要有一个方法:更新方法,即更新当前的内容,做出相应的处理。
- 添加监听者和移除监听者在不同的模型称谓中可能会有不同命名。