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

说明:

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

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

结构:

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

实例:

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

  1. #构造药品类和工作人员类
  2. class Medicine:
  3. name=""
  4. price=0.0
  5. def __init__(self,name,price):
  6. self.name=name
  7. self.price=price
  8. def getName(self):
  9. return self.name
  10. def setName(self,name):
  11. self.name=name
  12. def getPrice(self):
  13. return self.price
  14. def setPrice(self,price):
  15. self.price=price
  16. def accept(self,visitor):
  17. pass
  18. #药品类中有两个子类,抗生素和感冒药
  19. class Antibiotic(Medicine):
  20. def accept(self,visitor):
  21. visitor.visit(self)
  22. class Coldrex(Medicine):
  23. def accept(self,visitor):
  24. visitor.visit(self)
  25.  
  26. #工作人员分为划价员和药房管理员
  27. class Visitor:
  28. name=""
  29. def setName(self,name):
  30. self.name=name
  31. def visit(self,medicine):
  32. pass
  33. class Charger(Visitor):
  34. def visit(self,medicine):
  35. print("CHARGE: %s lists the Medicine %s. Price:%s " % (self.name,medicine.getName(),medicine.getPrice()))
  36. class Pharmacy(Visitor):
  37. def visit(self,medicine):
  38. print("PHARMACY:%s offers the Medicine %s. Price:%s" % (self.name,medicine.getName(),medicine.getPrice()))
  39.  
  40. """
  41. 在药品类中,有一个accept方法,其参数是个visitor;
  42. 而工作人员就是从Visitor类中继承而来的,
  43. 也就是说,他们就是Visitor,都包含一个visit方法,其参数又恰是medicine。
  44. 药品作为处理元素,依次允许(Accept)Visitor对其进行操作,
  45. 这就好比是一条流水线上的一个个工人,对产品进行一次次的加工。
  46. 整个业务流程还差一步,即药方类的构建(流水线大机器)
  47. """
  48.  
  49. class ObjectStructure:
  50. pass
  51. class Prescription(ObjectStructure):
  52. medicines=[]
  53. def addMedicine(self,medicine):
  54. self.medicines.append(medicine)
  55. def rmvMedicine(self,medicine):
  56. self.medicines.append(medicine)
  57. def visit(self,visitor):
  58. for medc in self.medicines:
  59. medc.accept(visitor)
  60. #药方类将待处理药品进行整理,并组织Visitor依次处理。
  61.  
  62. if __name__=="__main__":
  63. yinqiao_pill=Coldrex("Yinqiao Pill",2.0)
  64. penicillin=Antibiotic("Penicillin",3.0)
  65. doctor_prsrp=Prescription()
  66. doctor_prsrp.addMedicine(yinqiao_pill)
  67. doctor_prsrp.addMedicine(penicillin)
  68. charger=Charger()
  69. charger.setName("Doctor Strange")
  70. pharmacy=Pharmacy()
  71. pharmacy.setName("Doctor Wei")
  72. doctor_prsrp.visit(charger)
  73. 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. C#6.0语言规范(六) 转换

    转换能够被视为是一个特定类型的表达式.转换可能会导致给定类型的表达式被视为具有不同的类型,或者它可能导致没有类型的表达式获取类型.转换可以是隐式或显式的,这决定了是否需要显式转换.例如,从类型int到 ...

  2. MySQL笔记(4)---表

    1.前言 上一章记录了MySQL中的一些文件组成,以及相关作用和参数配置,本章开始记录深层次的存储结构,以便更好理解MySQL的设计. 2.索引组织表 InnoDB中,表都是根据主键顺序组织存放的,这 ...

  3. JAVA+SELENIUM+MAVEN+TESTNG框架(二)新建项目

    1.新建maven项目 2.下载selenium的jar包,放入maven依赖库中 3.新增testng依赖库,build path->add libirary->testng 4.查看自 ...

  4. vue传参页面刷新数据丢失问题

    在做vue的时候,经常会遇到组件之间数据的传递问题,通过params或者query传参,但是,当页面刷新的时候,数据会丢失,找不到数据.今天经过总结,解决了这个问题.通过了一下几种情况进行传值: 通过 ...

  5. Chapter 3 Phenomenon——19

    His unfriendliness intimidated me. 他的不友好恐吓到了我. My words came out with less severity than I'd intende ...

  6. es-01-简介

    1, 基于lucene的实时搜索软件 分布式的restful风格的搜索和数据分析引擎, 2, 和kibana, logstash 构成 elk生态圈 es: 数据存储和查询 kibana: 可视化 l ...

  7. mongo学习使用记录2 spring data

    spring data mongo 打印mongo NoSql语句 log4j.properties log4j.rootLogger=INFO, stdout log4j.logger.org.sp ...

  8. JDBC Oracle sys 用户连接

    Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager.getConnection( &quo ...

  9. Java创建线程的两种方式

    方式 继承Thread类 实现Runnable方法 实例 #继承Thread类 public class ThreadTest2 extends Thread { private int thread ...

  10. vuex数据管理-数据模块化

    对于vue这类mvvm框架来说,其核心就是组件与数据,因此做好相应的数据管理极为重要.这里分享下vuex数据模块化管理的方法,有利于搭建便于维护.协作的vue项目. vuex管理基本方法和使用 模块化 ...