当前位置: 首页 > 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…...

小白也能用的AI神器:Anything to RealCharacters 2.5D转真人引擎全流程体验

小白也能用的AI神器:Anything to RealCharacters 2.5D转真人引擎全流程体验 1. 从动漫到真人的神奇转换 你是否曾经想过,把自己喜欢的动漫角色变成真实人物会是什么样子?或者想把游戏中的虚拟形象变成一张可以打印的照片?现在&a…...

FigmaCN实战指南:3步实现Figma界面全中文化,提升设计师工作效率70%

FigmaCN实战指南:3步实现Figma界面全中文化,提升设计师工作效率70% 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN FigmaCN是一款专为中文设计师打造的开源浏览器…...

秦时明月6.2魔改版_从零到一部署指南_含安卓客户端调试与GM后台管理

1. 环境准备与基础配置 第一次接触游戏服务端搭建的朋友可能会觉得无从下手,但其实只要跟着步骤走,整个过程并不复杂。我去年在本地虚拟机成功部署过这个版本,最近又在云服务器上重新走了一遍流程,把最新遇到的坑都记录下来了。 先…...

分析Python条件变量如何暂停和唤醒线程

在开始前,先了解一下基本使用 Condition Condition 本质上是一个带有等待队列的锁,它封装了: 一个底层锁(Lock 或 RLock)一个等待者队列(_waiters) 核心方法方法作用wait(timeout)释放锁并阻塞等…...

ctfileGet:突破网盘限速的本地解析方案

ctfileGet:突破网盘限速的本地解析方案 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 在数字化办公与学习环境中,网盘已成为文件传输与存储的基础设施。然而,下载速…...

FreakStudio滞

环境安装 pip install keystone-engine capstone unicorn 这3个工具用法极其简单,下面通过示例来演示其用法。 Keystone 示例 from keystone import * CODE b"INC ECX; ADD EDX, ECX" try: ks Ks(KS_ARCH_X86, KS_MODE_64) encoding, count ks.…...

VINS-Mono代码架构深度解析:从feature_tracker到pose_graph,搞懂每个模块在做什么

VINS-Mono代码架构深度解析:从feature_tracker到pose_graph,搞懂每个模块在做什么 当你第一次成功运行VINS-Mono并看到实时轨迹在RVIZ中流畅呈现时,那种成就感不言而喻。但作为追求技术深度的开发者,我们不会满足于"能跑通&q…...

Kiro IDE + AIClient-2-API 实现Openclaw或者Claude code使用Claude Opus 4.6模型

前言:在AI辅助编程领域,Claude Opus 4.6 凭借强大的代码理解、生成和调试能力,成为很多开发者的首选模型。但直接使用 Anthropic 官方 API 不仅计费昂贵,额度也容易受限。本文将详细讲解如何通过「Kiro IDE AIClient-2-API Clau…...

Dell R730xd老将焕新记:保姆级教程搞定ESXi 8.0u3d,附网卡驱动避坑指南

Dell R730xd服务器升级ESXi 8.0u3d全流程实战指南 当企业IT基础设施进入更新周期,许多运维团队都会面临一个现实问题:那些曾经稳定服役多年的服务器硬件,是否还能适配最新的虚拟化平台?以Dell PowerEdge R730xd这款经典2U服务器为…...

Linux内核SLUB调试之slabinfo工具

前面我们介绍了Linux内核SLUB调试功能,现在我们来介绍一下slabinfo等相关的工具,这对于理解并调试slab缓存功能很有帮助。 slabinfo介绍 slabinfo 不是普通系统命令,而是内核源码自带的官方调试工具。 它的源码位于内核源码树的tools/mm/slabinfo.c,由内核社区直接维护,…...