源码地址:https://github.com/weilanhanf/PythonDesignPatterns

 

说明:

访问者模式的基本想法是,软件系统中拥有一个由许多对象构成的、比较稳定的对象结构,这些对象的类都拥有一个 accept 方法用来接受访问者对象的访问。访问者是一个接口,它拥有一个 visit 方法,这个方法对访问到的对象结构中不同类型的元素做出不同的处理。在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施 accept 方法,在每一个元素的 accept 方法中会调用访问者的 visit 方法,从而使访问者得以处理对象结构的每一个元素,我们可以针对对象结构设计不同的访问者类来完成不同的操作,达到区别对待的效果。

访问者模式定义:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。

 

结构:

抽象访问者,具体访问者,抽象元素,具体元素,对象结构。

实例:

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

#构造药品类和工作人员类
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

优点:

符合单一指责,凡是适用访问者模式的场景中,元素类中需要封装在访问者中的操作必定是与元素类本身关系不大且是易变的操作,使用访问者模式一方面符合单一职责原则,另一方面,因为被封装的操作通常来说都是易变的,所以当发生变化时,就可以在不改变元素类本身的前提下,实现对变化部分的扩展。扩展性良好,元素类可以通过接受不同的访问者来实现对不同操作的扩展。

缺点:

增加新的元素类很困难。在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,违背了“开闭原则”的要求。破坏封装。当采用访问者模式的时候,就会打破组合类的封装。

使用场景:

对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。

 

转载于:https://www.cnblogs.com/welan/p/9130622.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/451567.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/451567.shtml
英文地址,请注明出处:http://en.pswp.cn/news/451567.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试题:Fibonacci数列

题目描述:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。 方法1:递归 public class Solution {public int Fibonacci(int n) {if (n 0){retu…

“行到水穷处,坐看云起时.“

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 自由自在,随意而行, 只沿着流水向上,不知不觉的就走到了泉眼尽头, 无路可走的时候 &…

git commit -m和git commit -am

字面解释的话,git commit -m用于提交暂存区的文件;git commit -am用于提交跟踪过的文件 要理解它们的区别,首先要明白git的文件状态变化周期,如下图所示 工作目录下面的所有文件都不外乎这两种状态:已跟踪或未跟踪。已…

磁盘结构简介

这里讲的主要是网上所谓的老式磁盘,它是由一个个盘片组成的,我们先从个盘片结构讲起。如图1所示,图中的一圈圈灰色同心圆为一条条磁道,从圆心向外画直线,可以将磁道划分为若干个弧段,每个磁道上一个弧段被称…

java中的对象监视器

参考文章:监视器–JAVA同步基本概念 感谢作者分享!

Yii1.1 CGridView 简单使用

Yii1.1 CGridView 简单使用 配置model文件,返回CActiveDataProvider对象。public function search() {$criterianew CDbCriteria;$criteria->compare(title,$this->title,true);$criteria->compare(type,$this->type);$criteria->compare(addr,$this…

3个著名加密算法(MD5、RSA、DES)的解析

MD5的全称是Message-Digest Algorithm 5,在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明,经MD2、MD3和MD4发展而来。 MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法&#x…

想念我的大大的石

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 // ------- 甘愿用我的一生去追寻 ... 想念我的大石头: 想念会默默陪着我,一直从烈日咫尺坐到黄昏浸透蔓蔓云层…

Java 中的悲观锁、乐观锁、自旋锁、适应性自旋锁、偏向锁、轻量级锁、重量级锁、公平锁、非公平锁、可重入锁、共享锁等

参考文献: 不可不说的Java“锁”事 java并发进阶 感谢美团技术团队! 感谢JavaGuide!

Git 的origin和master解析

首先要明确一点,对git的操作是围绕3个大的步骤来展开的(其实几乎所有的SCM都是这样) 1. 从git取数据(git clone) 2. 改动代码 3. 将改动传回git(git push) 这3个步骤又涉及到两个re…

end to end testing

概念 https://www.softwaretestinghelp.com/what-is-end-to-end-testing/ What is “End to End Testing”? Term “End to End testing” is defined as a testing method which determines whether the performance of an application is as per the requirement or not. It…

windows下安装mysql 开机启动

1 下载地址 http://dev.mysql.com/downloads/installer/ 2 下载版本 mysql community server 5.7.x 这个版本是一个傻瓜版本,设置root密码之后就可以启动服务了,不用自己配置,还有workbench可用。转载于:https://www.cnblogs.com/hustdc/p/91…

Linux目录架构详解

Linux和Windows操作系统的显著区别之一就是目录架构的不同。Linux操作系统的目录架构遵循文件系统层级结构标准。不知你是否使用ls命令浏览过Linux的根目录“/”,亲爱的读者,您都了解这些目录的含义吗? ls -l / 遍历文件系统(点击…

越阳光明媚....

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 窗外阳光明媚,而心却如此哀伤... 很喜欢阳光明媚,很喜欢春暖花开, 窗外有几片庄稼地:满…

Linux的学习:

查看端口: netstat -anop | grep 80 netstat -ntlp 先看看不带n的 再看看带n的 我们发现在local address 即主机地址这一栏中,如果没有带n选项,会将套接字所对应的域名解析出来,如果加上n选项,那么就不会显示&#xff…

基于TCP协议的Socket通信

参考文章: Socket学习网络基础准备 基于TCP协议的Socket通信(1) 基于TCP协议的Socket通信(2) 感谢菜鸟分享!

git pull命令

git pull命令作用:从另一个存储库或本地分支关联的远端分支获取最新代码,并与本地代码资源整合。git pull命令执行过程:取回远程主机某个分支的更新,再与本地的指定分支合并(可能存在需手动解决的冲突)。 …

RPM的用法

RPM 有五种基本的操作方式(不包括创建软件包): 安装, 卸载, 升级, 查询,和验证。 下面我们就来逐一的讲解吧。 一、 安装RPM包 RPM 软件包通常具有类似foo-1.0-1.i386.rpm 的文件名。其中包括 软件包的名称(foo),版本号(1.0),发行号(1), 和 硬…

Unix 多进程编程

一.多进程程序的特点由于UNIX系统是分时多用户系统, CPU按时间片分配给各个用户使用, 而在实质上应该说CPU按时间片分配给各个进程使用, 每个进程都有自己的运行环境以使得在CPU做进程切换时不会"忘记"该进程已计算了一半的"半成品". 以DOS的概念来说, 进程…

Redis单线程模型是什么?

参考文章: redis 单线程的理解 谢谢作者分享!