设计模式 - 访问者模式

一、定义

1.      访问者模式(Visitor Pattern)是GoF提出的23种设计模式中的一种,属于行为模式。

2.      定义(源于GoF《Design Pattern》):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

3.      从定义可以看出结构对象是使用访问者模式必备条件,而且这个结构对象必须存在遍历自身各个对象的方法。这便类似于Java语言当中的collection概念了。

二、特点

1.      访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。

2.      访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。

3.      访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。

三、基本角色

1.      Visitor:抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。

2.      ConcreteVisitor:具体访问者角色,实现Visitor声明的接口。

3.      Element:抽象元素,定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。

4.      ConcreteElement:具体元素,实现了抽象元素(Element)所定义的接受操作接口。

5.      ObjectStructure:结构对象角色,这是使用访问者模式必备的角色。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。

访问者模式的基本角色关系如下图。

简单的说:Visitor和ConcreteVisitor分别是访问者的抽象类及实现类,Element和ConcreteElement分别是元素的抽象类及实现类,而ObjectStructure就是元素的容器。

四、简单例子

1.      根据访问者模式所要求的基本角色,我们可以建立一个最简单的例子,如下图所示的JAVA类

2.      访问者角色:在接口中定义了对应于每一个具体元素的visit操作。而实现类中各个访问者则进行自己不同的具体实现。

3.      元素角色:在抽象类中定义了用于接受访问者的accept方法。而实现类中,需要让该访问者可以visit自己。

4.      结构对象角色:在该容器中,需要持有多个具体的元素,以及遍历持有的元素的方法。

5.      使用:当需要对元素进行不同的操作时,就可以自由的创建不同的访问者角色,去访问结构对象角色中的各个元素对象了。

6.      可以看出,访问者模式实际上就是把数据结构和作用于数据结构上的操作解耦合

如果把该例子合并到一个类中,就是类似如图所示的类,既持有数据结构,也有作用于结构上的操作。

五、通俗例子

要在现实生活中寻找一个通俗的例子,我们可以以跑马场为例。

1.      结构对象角色 -> 跑马场(持有各种马的对象)

2.      抽象数据结构 -> 马

3.      具体数据结构 -> 黑马、白马……等具体的马

4.      抽象访问者   -> 顾客

5.      具体访问者   -> 张三、李四…… 等具体的顾客

跑马场持有各种马,这是数据(固定的)

跑马场的来访顾客是不特定的人群,这是操作(自由添加)

每个来访顾客,都可以用自己的方式骑马(新增访问者,实现不同的访问方法)

六、实际使用

1.      在使用ASM框架的类修改功能时,用的就是访问者模式,如图

2.      ClassReader类就是一个结构对象角色,用于来读取.class文件,并持有类文件中解析出来的各种元素

3.      ClassVisitor类就是一个抽象访问者,要修改类时,就自定义一个访问者实现类,如图中的ModifyClassVisitor类,进行每个用户不同的修改操作。

4.      ClassWriter类是用来输出修改后的类的信息,这里与访问者模式无关,是内置在访问者中的一个内部对象。

七、适用情况

1.      一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。

2.      需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor模式使得你可以将相关的操作集中起来定义在一个类中。

3.      当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。

4.      定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

八、附件下载

点击这里下载例子代码


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值