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

说明:

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

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

结构:

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

实例:

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

#构造药品类和工作人员类
class Medicine:
name=""
price=0.0
def __init__(self,name,price):
self.name=name
self.price=price
def getName(self):
return self.name
def setName(self,name):
self.name=name
def getPrice(self):
return self.price
def setPrice(self,price):
self.price=price
def 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=name
def 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

优点:

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

缺点:

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

使用场景:

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

python-访问者模式的更多相关文章

  1. 设计模式-行为型模式,python访问者模式

    访问者模式 在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法.通过这种方式,元素的执行算法可以随着访问者改变而改变.这种类型的设计模式属于行为型模式. ...

  2. [Python设计模式] 第28章 男人和女人——访问者模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目 用程序模拟以下不同情况: 男人成功时,背后多半有一个伟大的女人: 女人成功 ...

  3. python 设计模式之访问者模式

    写在前面 设计模式是经过总结.优化的,对我们经常会碰到的一些编程问题的可重用解决方案.一个设计模式并不像一个类或一个库那样能够直接作用于我们的代码.反之,设计模式更为高级,它是一种必须在特定情形下实现 ...

  4. .NET设计模式访问者模式

    一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...

  5. 访问者模式(visitorpattern)

    /** * 访问者模式 * @author TMAC-J * 在客户端和元素之间添加一个访问者 * 当你需要添加一些和元素关系不大的需求时,可以直接放在访问者里面 * 或者是元素之间有一些公共的代码块 ...

  6. C#设计模式-访问者模式

    一. 访问者(Vistor)模式 访问者模式是封装一些施加于某种数据结构之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保存不变.访问者模式适用于数据结构相对稳定的系统, 它把数据结 ...

  7. C#设计模式系列:访问者模式(Visitor)

    1.访问者模式简介 1.1>.定义 作用于某个对象群中各个对象的操作,可以使在不改变对象本身的情况下,定义作用于对象的新操作. 1.2>.使用频率   低 2.访问者模式结构 2.1> ...

  8. php实现设计模式之 访问者模式

    <?php /** * 访问者模式 * 封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作. * 行为类模式 */ /** 抽象访问者:抽象类或 ...

  9. 十一个行为模式之访问者模式(Visitor Pattern)

    定义: 提供一个作用于某对象结构(通常是一个对象集合)的操作的接口,使得在添加新的操作或者在添加新的元素时,不需要修改原有系统,就可以对各个对象进行操作. 结构图: Visitor:抽象访问者类,对元 ...

  10. 访问者模式(Visitor Pattern)

    定义:封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作. Visitor 抽象访问者角色:为该对象结构中具体元素角色声明一个访问操作接口.该操作接口 ...

随机推荐

  1. Shell - 简明Shell入门02 - 变量(Variable)

    示例脚本及注释 #!/bin/bash v1=test-variable_123 # 全局变量 v2=12345 v3='This is a test!' # 赋值语句使用单引号或双引号可以包含空格 ...

  2. python iter函数用法

    iter函数用法简述 Python 3中关于iter(object[, sentinel)]方法有两个参数. 使用iter(object)这种形式比较常见. iter(object, sentinel ...

  3. Hadoop集群搭建中时间同步步骤

        一.设置主节点时间服务器的时区     二.在每一个节点上检查是否安装时间服务ntp     三.在主节点上配置时间同步的相关文件     四.在其他从节点上配置与主节点时间同步的脚本 一.设 ...

  4. (转)计算机原理学习(1)-- 冯诺依曼体系和CPU工作原理

    原文:https://blog.csdn.net/cc_net/article/details/10419645 对于我们80后来说,最早接触计算机应该是在95年左右,那个时候最流行的一个词语是多媒体 ...

  5. python for dblp.xml

    由于最近处理数据时涉及到dblp.xml,刚开始下载时dblp.xml只有300多M,但解压之后就有1.9G,没有什么东西能够打开,所以必须要用工具来处理,在python中sax包能够一边解析一边处理 ...

  6. StreamSets学习系列之启动StreamSets时出现Caused by: java.security.AccessControlException: access denied ("java.util.PropertyPermission" "test.to.ensure.security.is.configured.correctly" "read")错误的解决办法

    不多说,直接上干货! 问题详情 [hadoop@master streamsets-datacollector-]$ ./bin/streamsets dc Java 1.8 detected; ad ...

  7. 第k大的数

    问题描述:输入一组数,指定一个k,输出这组数里第k大的数. 一般这种题目,第一想法是把整个数组先排序后,再选取第k位的数.但是这样做实际上浪费了大量的时间在排序上,我们只是要求第k大的数,并非要把整个 ...

  8. Ceph 块设备 - 块设备快速入门

    目录 一.准备工作 二.安装 Ceph 三.使用块存储   一.准备工作 本文描述如何安装 ceph 客户端,使用 Ceph 块设备 创建文件系统并挂载使用. 必须先完成 ceph 存储集群的搭建,并 ...

  9. APIX招聘

  10. gradle 转 maven

    1. 预备 1.1. java 环境 验证 java -version 1.2. gradle 安装, 参考, 这里列举下windows下的安装 b.1 下载包:https://gradle.org/ ...