定义:

  表示作用于某对象结构中的各个元素的操作。

  可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

前提:

  适用于数据结构(Element)相对稳定的系统,这样visitor中的方法就是稳定的。

不适用与数据结构易于变化的情况,不适用与此模式。如果总是有具体的Element加进来,visitor就需要增加新的方法,所有子类也需要增加,不符合开放-封闭原则。

  例如:算法和数据结构(前提:有比较稳定的数据结构),需要易于变化的算法,使得算法操作的增删改变得容易。

优点:

  把数据结构和作用于结构上的操作之间的耦合解开,使得操作集合可以相对自由地演化。即:把数据处理从数据结构分离出来。

增加新的操作很容易。增加新的操作意味着增加一个新的访问者(visitor),访问者模式将有关的行为集中到一个抽象对象中。

visitor可以单独开发,不必Element写在一起。visitor可以提高Element间的独立性。否则,每新增处理方法已扩充功能时,就必须修改ConcreteElementA、ConcreteElementB

缺点:

  增加新的数据结构变得困难。

Tip:

  很难找到数据结构不变化的情况,使用访问者模式的机会不多。

  大多时候并不需要访问者模式,但当一旦需要访问者模式时,就针对需要它了。

  访问者模式的能力、复杂性是把双刃剑,只有真正需要的时候,才可以考虑使用。

  需要好好理解其适用性。

结构图:

  访问者模式,visitor插图  

  访问者模式,visitor插图1

  访问者模式,visitor插图2

  访问者模式,visitor插图3

Visitor调用Element;Element调用Visitor。双分派技术,处理实现与数据结构分离。

示例:

  访问者模式,visitor插图4

  抽象类:关键在于人的分类(男人、女人)是稳定的。所以状态类中方法(男人反应、女人反应)个数是稳定的。抽象类人的抽象方法Accept(),用来获得状态对象。

  访问者模式,visitor插图5

  具体状态类:

  访问者模式,visitor插图6

  访问者模式,visitor插图7

  男人、女人类:

  使用双分派技术:

第一次分派:将具体状态作为参数传递给“具体(男人、女人)类”。数据结构调用操作

  第二次分派:具体(男人、女人)类调用“状态类”中的“男人、女人反应”,同时将自己(this:男人类、女人类)作为参数传递进去。操作使用数据结构中的数据

意味着:执行的操作取决于请求的种类(具体状态类)和接收者类型(男人、女人)。Accept()就是一个双分派的操作。

  访问者模式,visitor插图8

  对象结构类:

  针对不同状态,遍历男人、女人,得到不同反应

   访问者模式,visitor插图9

  客户端:

  访问者模式,visitor插图10

  访问者模式,visitor插图11

  优点:

  增加状态(结婚……),查看男人、女人放映,只需增加一个状态子类,客户端调用查看即可,不用改动其他任何类的代码。

  完美体现了“开放-封闭”原则。

  对比:

  访问者模式,visitor插图12

  访问者模式,visitor插图13

  客户端:

  访问者模式,visitor插图14

  访问者模式,visitor插图15

  结果:

  访问者模式,visitor插图16

发表回复

您的电子邮箱地址不会被公开。