当前位置: 首页 > news >正文

Python与设计模式--访问者模式

23种计模式之 前言 +(5)单例模式、工厂模式、简单工厂模式、抽象工厂模式、建造者模式、原型模式、+(7)代理模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式、桥梁模式、+(11)策略模式、责任链模式、命令模式、中介者模式、模板模式、迭代器模式、访问者模式、观察者模式、解释器模式、备忘录模式、状态模式 + 设计原则

18-Python与设计模式–访问者模式

一、药房业务系统

假设一个药房,有一些大夫,一个药品划价员和一个药房管理员,它们通过一个药房管理系统组织工作流程。
大夫开出药方后,药品划价员确定药品是否正常,价格是否正确;通过后药房管理员进行开药处理。
该系统可以如何实现?最简单的想法,是分别用一个一个ifelse…把划价员处理流程和药房管理流程实现,
这样做的问题在于,扩展性不强,而且单一性不强,一旦有新药的加入或者划价流程、开药流程有些变动,
会牵扯比较多的改动。今天介绍一种解决这类问题的模式:访问者模式。

首先,构造药品类和工作人员类:

class Medicine:name=""price=0.0def __init__(self,name,price):self.name=nameself.price=pricedef getName(self):return self.namedef setName(self,name):self.name=namedef getPrice(self):return self.pricedef setPrice(self,price):self.price=pricedef accept(self,visitor):pass
class Antibiotic(Medicine):def accept(self,visitor):visitor.visit(self)
class Coldrex(Medicine):def accept(self,visitor):visitor.visit(self)

药品类中有两个子类,抗生素和感冒药;

class Visitor:name=""def setName(self,name):self.name=namedef visit(self,medicine):pass
class Charger(Visitor):def visit(self,medicine):print "CHARGE: %s lists the Medicine %s. Price:%s " % (self.name,medicine.getName(),medicine.getPrice())
class Pharmacy(Visitor):def visit(self,medicine):print "PHARMACY:%s offers the Medicine %s. Price:%s" % (self.name,medicine.getName(),medicine.getPrice())
工作人员分为划价员和药房管理员。
在药品类中,有一个accept方法,其参数是个visitor;而工作人员就是从Visitor类中继承而来的,
也就是说,他们就是Visitor,都包含一个visit方法,其参数又恰是medicine。药品作为处理元素,
依次允许(Accept)Visitor对其进行操作,这就好比是一条流水线上的一个个工人,
对产品进行一次次的加工。整个业务流程还差一步,即药方类的构建(流水线大机器)。
class ObjectStructure:pass
class Prescription(ObjectStructure):medicines=[]def addMedicine(self,medicine):self.medicines.append(medicine)def rmvMedicine(self,medicine):self.medicines.append(medicine)def visit(self,visitor):for medc in self.medicines:medc.accept(visitor)

药方类将待处理药品进行整理,并组织Visitor依次处理。

业务代码如下:

if __name__=="__main__":yinqiao_pill=Coldrex("Yinqiao Pill",2.0)penicillin=Antibiotic("Penicillin",3.0)doctor_prsrp=Prescription()doctor_prsrp.addMedicine(yinqiao_pill)doctor_prsrp.addMedicine(penicillin)
charger=Charger()
charger.setName("Doctor Strange")
pharmacy=Pharmacy()
pharmacy.setName("Doctor Wei")
doctor_prsrp.visit(charger)
doctor_prsrp.visit(pharmacy)

打印如下:

CHARGE: Doctor Strange lists the Medicine Yinqiao Pill. Price:2.0
CHARGE: Doctor Strange lists the Medicine Penicillin. Price:3.0
PHARMACY:Doctor Wei offers the Medicine Yinqiao Pill. Price:2.0
PHARMACY:Doctor Wei offers the Medicine Penicillin. Price:3.0

二、访问者模式

访问者模式的定义如下:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下
定义于作用于这些元素的新操作。
提到访问者模式,就不得不提一下双分派。分派分为静态分派和动态分派。首先解释下静态分派,静态分派即
根据请求者的名称和接收到的参数,决定多态时处理的操作。比如在Java或者C++中,定义名称相同但参数不同
的函数时,会根据最终输入的参数来决定调用哪个函数。双分派顾名思义,即最终的操作决定于两个接收者的
类型,在本例中,药品和工作人员互相调用了对方(药品的accept和工作人员的visit中,对方都是参数),
就是双分派的一种应用。
那么Python支持静态分派么?先看下面的一个例子。
def max_num(x,y,z):return max(max(x,y),z)
def max_num(x,y):return max(x,y)
if __name__=="__main__":print max_num(1,2,4)

打印如下:

Traceback (most recent call last): File
“D:/WorkSpace/Project/PyDesignMode/example.py”, line 786, in

print max_num(1,2,4)
TypeError: max_num() takes exactly 2 arguments (3 given)

可见,Python原生是不支持静态分派的,因而也不直接支持更高层次的分派。访问者模式实现的分派,
、是一种动态双分派。但这并不妨碍Python通过访问者模式实现一种基于类的“双分派效果”。
Python多分派可以参考David Mertz 博士的一篇文章:可爱的Python:多分派—用多元法泛化多样性。

三、访问者模式的优点和应用场景

优点:
1、将不同的职责非常明确地分离开来,符合单一职责原则;
2、职责的分开也直接导致扩展非常优良,灵活性非常高,加减元素和访问者都非常容易。应用场景:
1、要遍历不同的对象,根据对象进行不同的操作的场景;或者一个对象被多个不同对象顺次处理的情况,
可以考虑使用访问者模式。除本例外,报表生成器也可以使用访问者模式实现,报表的数据源由多个不同的
对象提供,每个对象都是Visitor,报表这个Element顺次Accept各访问者完善并生成对象。

四、访问者模式的缺点

1、访问者得知了元素细节,与最小隔离原则相悖;
2、元素变更依旧可能引起Visitor的修改。

相关文章:

Python与设计模式--访问者模式

23种计模式之 前言 (5)单例模式、工厂模式、简单工厂模式、抽象工厂模式、建造者模式、原型模式、(7)代理模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式、桥梁模式、(11)策略模式、责任链模式、命令模式、中介者模…...

为社会做贡献的EasyDarwin 4.0.1发布了,支持视频点播、文件直播、摄像机直播、直播录像、直播回放、录像MP4合成下载

经过几个月的不懈努力和测试,最新的EasyDarwin 4.0版本总算是发布出来了,功能还是老几样:文件点播、视频直播(支持各种视频源)、直播录像与回放、录像合成MP4下载,稍稍看一下细节: 文件上传与点…...

CG向量和矩阵元素的获取

swizzle swizzle可以获取向量分量值;表现形式是点符号和rgba或xyzw rgba一般用作颜色表示 xyzw一般用于坐标表示分量值可以进行组合 例如:fixed4 test(1,2,3,4) 获取分量值:test.r 获取第一个分量值、test.g、test.xy、test.yx 向量维度转换…...

牛客 算法题 golang语言实现

题目 HJ101 输入整型数组和排序标识,对其元素按照升序或降序进行排序 描述 输入整型数组和排序标识,对其元素按照升序或降序进行排序数据范围: 1 ≤ � ≤ 10001≤n≤1000 ,元素大小满足 0 ≤ � &#…...

鸿蒙开发报错:agconnect sdk not initialized. please call initialize()【BUG已解决】

文章目录 项目场景:问题描述原因分析:解决方案:总结:项目场景: 鸿蒙开发报错: agconnect sdk not initialized. please call initialize() 问题描述 报错内容为: 10-25 11:41:01.152 6076-16676 E A0c0d0/JSApp: app Log: 数据查询失败: {“code”:1100001,“messag…...

极智芯 | 解读国产AI算力算能产品矩阵

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文分享一下 解读国产AI算力 华为昇腾产品矩阵。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq 算能属于自研 TPU 阵营,…...

docker介绍、部署与常用命令

一、docker 介绍 1、容器(Container): (1) 概念: 容器是一种用于运行和部署应用程序的技术。它将应用程序及其所有依赖项(例如代码、运行时、系统工具、系统库等)打包在一个独立的、可移植的运行环境中&…...

windows定时任务命令工具schtasks

1.Schtasks概述 schtasks 是 Windows 操作系统中用于调度任务的命令行工具。它允许你在指定的时间或事件触发时运行程序或脚本。通过 schtasks 命令,你可以创建、修改、查询和删除计划任务。 2.Schtasks常用命令 查看帮助文档 schtasks /? 设定每月1号执行数据…...

多个nginx共享值、缓存问题

背景 目前我在集成登录认证功能(cas),使用的架构是nginxlua,由于我们有多个系统(全是前端项目),每套系统都采用nginxlua的方式进行部署(即每个系统都是一个nginx)&#…...

【2023传智杯】第六届传智杯程序设计挑战赛AB组-DEF题解题分析详解【JavaPythonC++解题笔记】

本文仅为【2023传智杯】第六届传智杯程序设计挑战赛-题目解题分析详解的解题个人笔记,个人解题分析记录。 本文包含:第六届传智杯程序设计挑战赛题目、解题思路分析、解题代码、解题代码详解 文章目录 一.前言更新进度记录二.比赛题目(AB俩组)D题题目-abbE题题目 -kotori和…...

Spark---SparkCore(五)

五、Spark Shuffle文件寻址 1、Shuffle文件寻址 1)、MapOutputTracker MapOutputTracker是Spark架构中的一个模块,是一个主从架构。管理磁盘小文件的地址。 MapOutputTrackerMaster是主对象,存在于Driver中。MapOutputTrackerWorker是从对…...

k8s中pod的hostport端口突然无法访问故障处理

故障背景: 租户告知生产环境的sftp突然无法访问了,登录环境查看sftp服务运行都是正常的,访问sftp的hostport端口确实不通。 故障处理过程 既然访问不通那就先给服务做个全面检查,看看哪里出了问题,看下sftp日志&#…...

高德开始“跑腿”

在这个万物皆可到家的时代,外卖已经不仅仅只送餐饮了,无论是鲜花、生活用品,亦或是其他急需品,只需要一个订单,就能够通通搞定。而随着消费者需求的增加,以即时物流为代表的新业态也顺势而起,并…...

Notion for Mac:打造您的专属多功能办公笔记软件

在如今这个信息爆炸的时代,一款高效、便捷的笔记软件对于办公人士来说已经成为必不可少的工具。Notion for Mac,作为一款多功能办公笔记软件,凭借其简洁优雅的界面、强大的功能以及无缝的云端同步,成为了众多用户的首选。 一、多…...

pip 安装软件出现 [No space left on device]

问题: /home文件下空间满了,安装软件可能会出现这个问题 解决方法: pip install --no-cache-dir 安装包名...

【算法刷题】Day8

文章目录 202. 快乐数解法: 11. 盛最多水的容器解法: 202. 快乐数 原题链接 拿到题,我们先看题干 把一个整数替换为每个位置上的数字平方和,有两种情况: 重复这个过程始终不到 1(无限死循环)结…...

基于单片机的智能饮水机控制系统(论文+源码)

1. 系统设计 本次智能饮水机控制系统的设计研究一款以STC89C52单片机为核心的智能饮水机控制系统,其主要功能设计如下: 1.该饮水机利用DS18B20数字温度传感器实时采集饮水机内水的温度,其检测温度范围为0-100℃,精度0.1℃&#…...

电脑格式化了怎么恢复原来的数据?您可以这样做

电脑是我们日常生活和工作中不可或缺的工具,然而,在一些情况下我们可能需要进行电脑格式化,比如为了清理系统垃圾、解决系统故障等。然而,格式化会导致所有数据被删除,给用户带来不便和困扰。本文将介绍电脑格式化了怎…...

mysql 性能排查

mysql 下常见遇到的问题有,mysql连接池耗尽,死锁、慢查、未提交的事务。等等我们可能需要看;我们想要查看的可能有 1.当前连接池连接了哪些客户端,进行了哪些操作 2.当前造成死锁的语句有哪些,是哪个客户端上的&#x…...

SpringBoot+网易邮箱登录注册

文章目录 SpringBoot网易邮箱登录注册pom.xmlapplication.ymlsqlUserEmail.javaUserEmailMapper.javaUserEmailMapper.xmlEmailService.javaUserEmailService.javaUserEmailServiceImpl.javaUserEmailController.javaregister1.html 编写前参考 SpringBoot网易邮箱登录注册 po…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

ios苹果系统,js 滑动屏幕、锚定无效

现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

Map相关知识

数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

如何在网页里填写 PDF 表格?

有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据&#xff…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) ​遍历字符串​:通过外层循环逐一检查每个字符。​遇到 ? 时处理​: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: ​与…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter

java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...

Python爬虫实战:研究Restkit库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...