行为模式 - 9 访问者模式

访问者模式,Visitor,使用访问者类,改变元素类本身的执行方法。通过这种方式,元素的执行算法可以随着访问者改变而改变。
 
想象一下,对于某一类对象,这些对象都是某个抽象类的具体实现,我们想对他们做访问,会怎么做?
 
> InterfaceA  ConcreteClassX  ConcreteClassY  ConcreteClassZ
 
方案1:
    在 InterfaceA 的内部增加一个 visit 方法,然后每个 ConcreteClass 都实现 visit 方法,在访问对象时,调用 visit 方法,执行想要的逻辑。
    这种方案破坏了原有类的结构,把每个对象的访问逻辑放在了具体的类中,当新增一种 visit 方法,具体类的实现也需要跟着做相应改变,不符合开闭原则。
 
方案2:
    把访问逻辑放在使用方,使用方想访问对象,就去主动获取对象中的元素,对于每一种访问,就设计一套具体的访问方法
    如果增加一个访问方式,就要添加方法,也不符合开闭原则。但是统一访问思想是对的。
 
    所以我们希望:访问的实现不要和被访问的对象有关系,而是依赖倒置的,访问者提供访问的实现,被访问的对象只需要调用访问者的实现。同时,被访问对象可以选择无需对访问者暴露内部元素,它可以主动的调用 vistor(只提供想给它的参数)。所以对访问者来说,它有访问操作上的自由,而对于被访问者来说,它有提供被访问元素的自由。
 
  1. 抽象出来一个 visitor 类,这个类用于主动访问对象
  2. 给抽象的 interfaceA 加一个 visit 方法, 接受 visitor 对象,visit 方法决定了自己被访问的元素,可以是自己,当然也可以是某个元素
  3. interfaceA 的具体类,实现这个 visit 方法,方法只是调用 visitor,主动传给它想要的元素
 
 
网上比较奇怪的是,总喜欢把一个具体的对象传给visitor,然后visitor去调用具体对象的operate方法,这样,操作的逻辑还是operate来控制,而visitor似乎啥也没干,或者打一个日志,有毒的逻辑。
 
一般,在讲解时,要有个ObjectStructure对象,这个对象的作用是什么?
一个元素的容器,一般包含一个容纳多个不同类、不同接口的容器,如List、Set、Map等,在项目中一般很少抽象出这个角色。
这个对象可以同样实现元素的接口,像不像代理模式?只不过是批量代理。。。
 
比如这里:而且Visitor居然提供多个visit方法
 
    假如一个对象中存在着一些与本对象不相干(或者关系较弱)的操作,为了避免这些操作污染这个对象,则可以使用访问者模式来把这些操作封装到访问者中去。假如一组对象中,存在着相似的操作,为了避免出现大量重复的代码,也可以将这些重复的操作封装到访问者中去。
 
    但是,访问者模式并不是那么完美,它也有着致命的缺陷:增加新的元素类比较困难。通过访问者模式的代码可以看到,在访问者类中,每一个元素类都有它对应的处理方法,也就是说,每增加一个元素类都需要修改访问者类(也包括访问者类的子类或者实现类),修改起来相当麻烦。也就是说,在元素类数目不确定的情况下,应该慎用访问者模式。所以,访问者模式比较适用于对已有功能的重构,比如说,一个项目的基本功能已经确定下来,元素类的数据已经基本确定下来不会变了,会变的只是这些元素内的相关操作,这时候,我们可以使用访问者模式对原有的代码进行重构一遍,这样一来,就可以在不修改各个元素类的情况下,对原有功能进行修改。
 
 
 
对于上面的描述,应该是对应这个代码块,个人觉得没有必要这样,Visitor提供一个visit方法已经足够,何必要对应每个具体的Element提供一个方法呢,可以用访问者模式+策略模式,在上层(调用方或者结构对象处)控制选择具体的Visitor。

猜你喜欢

转载自www.cnblogs.com/43726581Gavin/p/9048451.html
今日推荐