目录

1.什么是监听模式

2.监听模式设计思想

3.监听模式的框架模型

4.分别用框架模型和不用框架模型来解决下面的例子

5.模型说明

6.监听模式根据侧重可以分为推模型和拉模型

7.账号异常登录检测和诊断机制

8.应用场景

1.什么是监听模式

监听模式又名观察者模式,顾名思义就是观察者与被观察的关系。比如在烧开水的时候它开没开,你就是观察者,水就是被观察者,等等像这种的模式。

2.监听模式设计思想

观察者模式是对象的行为模式。

监听模式的核心思想就是在被观察者与观察者之间建立一种自动触发的关系。

监听模式是一种一对多的关系,可以有一个或者多个观察者对象同时监听某一个对象。监听的对象叫观察者(监听者),被监听的对象叫被观察者(Observable,也叫主题,即Subject)。被观察者对象在状态或内容(数据)发生变化时,会通知所有观察者对象,使它们能够做出相应的变化(如自动更新自己的信息)

3.监听模式的框架模型

from abc import ABCMeta, abstractmethod# 引入ABCMeta 和 abstractmethod 来定义抽象类和抽象方法# metaclass=ABCMeta : 使创建的类为抽象类
class Observer(metaclass=ABCMeta):"""观察者的基类"""@abstractmethoddef updata(self, observalbe, object):passclass 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.updata(self, object)

Observable是被观察者的抽象类,Observer是观察者的抽象类。  另外还有三个方法,分别用于添加和删除观察者,notifyObservers 用于内容或状态变化时通知所有的观察者。因为Observable的notifyObservers会调用Observer的update方法,所有观察者不需要关心被观察者的对象什么时候会发生变化,只要有变化就会自动调用update,所以只需要关注update实现就可以了。

4.分别用框架模型和不用框架模型来解决下面的例子

简单的例子,比如热水器热水,到多少度可以饮用,到多少度可以洗澡的问题,

不用框架模型

from abc import ABCMeta, abstractmethod# 热水器类
class WaterHeater:def __init__(self):# 观察者的数量self.__observers = []# 设置初始温度self.__temperature = 25# 获取温度def getTemperature(self):return self.__temperature# 设置温度def setTemperature(self, temperature):self.__temperature = temperatureprint("当前的温度是", str(temperature), "℃")# 调用notifies方法,其实就是调用每个观察者中的updateself.notifies()def addObserver(self, observer):self.__observers.append(observer)def notifies(self):for o in self.__observers:o.update(self, )# 创建观察者的抽象类
class Observer(metaclass=ABCMeta):"""观察者的基类"""@abstractmethoddef update(self, observalbe, object):pass# 洗澡的类WashingMode继承父类Observer
class WashingMode(Observer):# 重写父类中静态方法updatedef update(self, waterHeater, **kwargs):if 50 <= waterHeater.getTemperature() <= 70:print("水已经烧好,可以洗澡")# 喝水的类DrinkingMode继承父类Observer
class DrinkingMode(Observer):# 重写父类中静态方法updatedef update(self, waterHeater, **kwargs):if waterHeater.getTemperature() >= 100:print("水已经烧开,可以饮用了")def testWaterHeatper():heater = WaterHeater()  # 创建热水器类的对象washingObser = WashingMode()  # 创建洗澡类的对象drinkingObser = DrinkingMode()  # 创建喝水类的对象# 调用热水器对象的添加观察者(洗澡类对象)的方法heater.addObserver(washingObser)# 调用热水器对象的添加观察者(喝水类对象)的方法heater.addObserver(drinkingObser)# 设置各种温度heater.setTemperature(40)heater.setTemperature(60)heater.setTemperature(100)# 调用测试方法
testWaterHeatper()
"""
运行结果:
当前的温度是 40 ℃
当前的温度是 60 ℃
水已经烧好,可以洗澡
当前的温度是 100 ℃
水已经烧开,可以饮用了
"""

使用框架模型

# @Time    : 2020/9/27 11:56
# @Author  : GodWei
# @File    : observerPattern.pyfrom abc import ABCMeta, abstractmethod, ABC# 引入ABCMeta 和 abstractmethod 来定义抽象类和抽象方法# metaclass=ABCMeta : 使创建的类为抽象类
class Observer(metaclass=ABCMeta):"""观察者的基类"""@abstractmethoddef update(self, observable, object):passclass 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 WasterHeater(Observable):"""热水器的类,继承父类(被观察者的抽象类)"""def __init__(self):super().__init__()self.__temperature = 25def getTemperature(self):return self.__temperaturedef setTemperature(self, temperature):self.__temperature = temperatureprint("当前的温度是", str(temperature), "℃")self.notifyObservers()class WashingMode(Observer):"""洗澡的类,继承父类(观察者的抽象类)"""def update(self, observable, object):if isinstance(observable, WasterHeater) \and 50 <= observable.getTemperature() <= 70:print("水已经烧好,可以洗澡")class DrinkingMode(Observer):"""喝水的类,继承父类(观察者的抽象类)"""def update(self, observable, object):if isinstance(observable, WasterHeater) \and  observable.getTemperature() >= 100:print("水已经烧开,可以饮用")def testWaterHeatper():heater = WasterHeater()  # 创建热水器类的对象washingObser = WashingMode()  # 创建洗澡类的对象drinkingObser = DrinkingMode()  # 创建喝水类的对象# 调用热水器对象的添加观察者(洗澡类对象)的方法heater.addObserver(washingObser)# 调用热水器对象的添加观察者(喝水类对象)的方法heater.addObserver(drinkingObser)# 设置各种温度heater.setTemperature(40)heater.setTemperature(60)heater.setTemperature(100)# 调用测试方法
testWaterHeatper()
"""
运行结果:
当前的温度是 40 ℃
当前的温度是 60 ℃
水已经烧好,可以洗澡
当前的温度是 100 ℃
水已经烧开,可以饮用
"""

结果是一样的,使用框架后,结构更新清晰,直接用观察者被观察者的父类继承即可

5.模型说明

(1)要明确谁是观察者谁是被观察者,问题也就明白了。一般观察者与被观察者之间是多对一的关系,一个被观察者对象可以有多个监听对象(观察者)。

(2) 被观察者至少需要有三个方法:添加监听者,移除监听者,通知Observer的方法。观察者至少要有一个方法:更新方法,即更新当前的内容,做出相应的处理

6.监听模式根据侧重可以分为推模型和拉模型

(1) 推模型:被观察者对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。一般在这种模型的实现中,会把观察者对象中的全部或部分信息通过update参数传递给观察者

(2) 拉模型: 被观察者在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到被观察者对象中获取,相当于观察者从被观察者对象中拉数据。一般在这种模型中,会把被观察者对象自身通过update方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了。

7.账号异常登录检测和诊断机制

服务器会记录最近登录的时间、地区、IP地址等,从而知道常用的登录地区,如果检测出哪一次登录和平时的地区相差非常大,则认为是一次异常登录, 只要登录异常一出现就自动发送信息,短信和邮箱的发送机制我们就可以认为是登录的观察者。

import time
from abc import ABCMeta, abstractmethod# 使用监听模式的框架
class Observer(metaclass=ABCMeta):"""观察者的基类"""@abstractmethoddef update(self, observable, object):passclass 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 Account(Observable):"""用户账户"""def __init__(self):super().__init__()self.__latestIp = {}self.__latestRegion = {}def login(self, name, ip, time):region = self.__getRegion(ip)if self.__isLongDistance(name, region):self.notifyObservers({"name": name, "ip": ip, "region": region, "time": time})self.__latestRegion[name] = regionself.__latestIp[name] = ipdef __getRegion(self, ip):"""由Ip地址获取地区信息,(只是进行模拟)"""ipRegions = {"117.23.33.34": "陕西省咸阳市","66.117.31.255": "美国洛杉矶"}region = ipRegions.get(ip)if region is None:return ""else:return regiondef __isLongDistance(self, name, region):"""计算本次登录与最近登录的地区差距(只是简单的进行模拟,用字符串匹配模拟) """latestRegion = self.__latestRegion.get(name)if latestRegion is not None and latestRegion != region:return latestRegionclass SmsSender(Observer):"""短信发送器"""def update(self, observable, object):print("【短信发送】" + object["name"] + "您好!系统检测到您的账户可能登录异常。最近一次登录信息:\n"+ "  登录地区:" + object["region"] + "  登录ip :" + object["ip"] +"  登录时间:" + time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(object["time"])))class MailSender(Observer):"""邮件发送器"""def update(self, observable, object):print("【邮件发送】" + object["name"] + "您好!系统检测到您的账户可能登录异常。最近一次登录信息:\n"+ "  登录地区:" + object["region"] + "  登录ip :" + object["ip"] +"  登录时间:" + time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(object["time"])))def testLogin():accout = Account()accout.addObserver(SmsSender())accout.addObserver(MailSender())accout.login("GodWei ", "117.23.33.34", time.time())accout.login("GodWei ", "66.117.31.255", time.time())testLogin()

运行结果:

"""
【短信发送】GodWei 您好!系统检测到您的账户可能登录异常。最近一次登录信息:登录地区:美国洛杉矶  登录ip :66.117.31.255  登录时间:2020-09-28 09:21:25
【邮件发送】GodWei 您好!系统检测到您的账户可能登录异常。最近一次登录信息:登录地区:美国洛杉矶  登录ip :66.117.31.255  登录时间:2020-09-28 09:21:25
"""

这段代码只是用来简单模拟程序,而且只记录了上一次的登录信息到Account对象中

实际项目中,像用户的信息,登录时间,ip,最近登录的情况,都存在数据库中。

8.应用场景

(1) 对一个对象状态或数据的更新需要其他对象同步更新,或者一个对象的更新需要依赖另一个对象的更新

(2) 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节,如消息推送

1.设计模式中监听模式(观察者模式)(Python实现)相关推荐

  1. 【转】第01课:生活中的监听模式——一坑爹的热水器

    用程序来模拟生活 从剧情中思考监听模式 监听模式 监听模式的模型抽象 代码框架 类图 基于框架的实现 模型说明 设计要点 推模型和拉模型 应用场景 [故事剧情] 刚刚大学毕业的 Tony 只身来到北京 ...

  2. 软件设计模式——监听模式

    摘要 本博文主要是介绍监听模式的原理和应用场景. 案例介绍 庄小焱毕业后留在了的城市,开始了沪漂的生活.但刚刚毕业的他身无绝技.包无分文,为了生活只能住在高桥镇的小村庄,每天坐着程序员专线(10号线) ...

  3. 第01课:生活中的监听模式——一坑爹的热水器

    用程序来模拟生活 从剧情中思考监听模式 监听模式 监听模式的模型抽象 代码框架 类图 基于框架的实现 模型说明 设计要点 推模型和拉模型 应用场景 [故事剧情] 刚刚大学毕业的 Tony 只身来到北京 ...

  4. 设计模式之观察者模式(监听模式)

    目录 前言 UML类图 观察者模式的设计要点及应用场景 观察者模式的应用 其他 前言         观察者模式也称作监听模式,即观察与被观察的关系,比如你在烧开水时看它有没有开,你就是观察者,水就是 ...

  5. 查看无线网卡是否支持监听模式

    查看无线网卡是否支持监听模式 在实施无线渗透测试时,通常需要将无线网卡设置为监听模式,来监听经过其网卡的所有流量.大学霸IT达人对于很多用户,都不知道如何确定自己的无线网卡是否支持监听,结果浪费大量时 ...

  6. JMS调用IBM MQ监听模式

    最近几天一直纠结于监听模式.在监听模式下遇到了两个问题. 1.消息接收者不关闭竟然收不到消息. 2.在监听模式下,每次只收一条消息,即使设定了监听,也是只收到一条消息 今天就针对这两个问题作出解答. ...

  7. kali linux wifi监听模式,无线渗透教程1:监听无线网络

    第一:配置管理无线网卡 1.1这里,我们使用tplink wn722n, kali linux插上即用,无需安装驱动. 1.2Vmare虚拟机配置如下: 如网卡插入到电脑后,先将虚拟机设置成桥接模式 ...

  8. 无线网卡设置为监听模式 airodump破解wifi

    linux下将无线网卡工作模式切换为监听模式 首先使用如下操作设置为监听模式: #ifconfig wlan0 down  //没有错误提示就是成功 #iwconfig wlan0 mode moni ...

  9. linux网卡混杂模式和监听模式

    混杂模式(promiscuous mode)是电脑网络中的术语.是指一台机器的网卡能够接收所有经过它的数据流,而不论其目的地址是否是它. 一般计算机网卡都工作在非混杂模式下,此时网卡只接受来自网络端口 ...

最新文章

  1. 通过sqlserver日志恢复误删除的数据
  2. C#实现对象的Xml格式序列化及反序列化
  3. 【CyberSecurityLearning 43】安装并启用telnet、SSH服务应用(★)
  4. nvidia linux屏幕撕裂,带有Nvidia/Intel图形的Ubuntu屏幕破裂
  5. ubuntu10.04下安装Eclipse
  6. hadoop学习日志
  7. [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)
  8. Android小知识10则(下)
  9. 成也英雄,败也英雄—Sun前CEO Scott Mc- Nealy
  10. phpeclipse中操作svn
  11. Ubuntu20.04安装ros教程(实测有用)
  12. MATLAB线性方程组的两种求解,matlab求解线性方程组
  13. 新唐单片机选型手册_Nuvoton新唐8位8051单片机选型指南
  14. 搭建亿万级别短信服务发送平台
  15. python selenium ActionChains类与鼠标的模拟事件
  16. 网盘容量背后的技术秘密
  17. 计算机两个用户怎么设置密码,电脑如何设置密码 电脑密码三个设置
  18. 多线程_12_优先级
  19. 柱承重式钢模块建筑结构体系适用高度研究
  20. [图论] 平面图 平面性的判定

热门文章

  1. 如何从官方渠道下载Spring MVC所需jar包
  2. php软件安装及调试_PHP调试利器XDebug的安装与使用
  3. k型热电偶分度表_一张表搞定热电偶与热电阻的问题
  4. springboot集成spring security安全框架入门篇
  5. CHM文件显示目录无法显示内容的解决方案
  6. 记一个mysql分页查询优化试验
  7. 【笔记】opencv的python使用 腐蚀模糊背景分割等处理图像
  8. Tomcat6 Spring3 问题:严重: Error configuring application listener of class org.springframework.web.conte
  9. oracle 11g备份,导入oracle 10g
  10. Android性能优化——内存泄漏优化