首页 > 代码库 > 访问者模式

访问者模式

● Visitor——抽象访问者

抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是visit方法的参数定

义哪些对象是可以被访问的。

● ConcreteVisitor——具体访问者

它影响访问者访问到一个类后该怎么干,要做什么事情。

● Element——抽象元素

接口或者抽象类,声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定

义的。

● ConcreteElement——具体元素

实现accept方法,通常是visitor.visit(this),基本上都形成了一种模式了。

● ObjectStruture——结构对象

元素产生者,一般容纳在多个不同类、不同接口的容器,如List、Set、Map等,在项目

中,一般很少抽象出这个角色。

 

抽象元素

 

public abstract class Element {

 

     //定义业务逻辑

 

     public abstract void doSomething();

 

     //允许谁来访问

 

     public abstract void accept(IVisitor visitor);

 

}

 

抽象元素有两类方法:一是本身的业务逻辑,也就是元素作为一个业务处理单元必须完

 

成的职责;另外一个是允许哪一个访问者来访问。

 

具体元素

 

public class ConcreteElement1 extends Element{

 

     //完善业务逻辑

 

     public void doSomething(){

 

             //业务处理

 

     }

 

     //允许那个访问者访问

 

     public void accept(IVisitor visitor){

 

             visitor.visit(this);

 

     }

 

}

 

public class ConcreteElement2 extends Element{

 

     //完善业务逻辑

 

     public void doSomething(){

 

             //业务处理

 

     }

 

     //允许那个访问者访问

 

     public void accept(IVisitor visitor){

 

             visitor.visit(this);

 

     }

 

}

 

它定义了两个具体元素,我们再来看抽象访问者,一般是有几个具体元素就有几个访问

 

方法

 

抽象访问者

 

 

 

public interface IVisitor {

 

     //可以访问哪些对象

 

     public void visit(ConcreteElement1 el1);

 

     public void visit(ConcreteElement2 el2);

 

}

 具体访问者

public class Visitor implements IVisitor {

     //访问el1元素

     public void visit(ConcreteElement1 el1) {

             el1.doSomething();

     }

     //访问el2元素

     public void visit(ConcreteElement2 el2) {

             el2.doSomething();

     }

}

结构对象是产生出不同的元素对象

 

结构对象

 

public class ObjectStruture {

 

     //对象生成器,这里通过一个工厂方法模式模拟

 

     public static Element createElement(){

 

             Random rand = new Random();

 

             if(rand.nextInt(100) > 50){

 

                     return new ConcreteElement1();

 

             }else{

 

                     return new ConcreteElement2();

 

             }

 

     }

 

}

场景类

public class Client {

     public static void main(String[] args) {

             for(int i=0;i<10;i++){

                     //获得元素对象

HuDun Demo

                     Element el = ObjectStruture.createElement();

                     //接受访问者访问

                     el.accept(new Visitor());

             }          

     }

}

通过增加访问者,只要是具体元素就非常容易访问,对元素的遍历就更加容易了,甭管

它是什么对象,只要它在一个容器中,都可以通过访问者来访问,任务集中化。这就是访问

者模式。

 

访问者模式的优点

 

● 符合单一职责原则

 

具体元素角色也就是Employee抽象类的两个子类负责数据的加载,而Visitor类则负责报

 

表的展现,两个不同的职责非常明确地分离开来,各自演绎变化。

 

● 优秀的扩展性

 

由于职责分开,继续增加对数据的操作是非常快捷的

 

● 灵活性非常高

访问者模式的缺点

● 具体元素对访问者公布细节

访问者要访问一个类就必然要求这个类公布一些方法和数据,也就是说访问者关注了其

他类的内部细节,这是迪米特法则所不建议的。

● 具体元素变更比较困难

具体元素角色的增加、删除、修改都是比较困难的

 

● 违背了依赖倒置转原则

 

访问者依赖的是具体元素,而不是抽象元素,这破坏了依赖倒置原则,特别是在面向对

 

象的编程中,抛弃了对接口的依赖,而直接依赖实现类,扩展比较难。

 

访问者模式的使用场景

 

● 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖

 

于其具体类的操作,也就说是用迭代器模式已经不能胜任的情景。

 

● 需要对一个对象结构中的对象进行很多不同并且不相关的操作,而你想避免让这些操

 

“污染”这些对象的类。

访问者模式还有一个用途,就是充当拦截器(Interceptor)角色

 

访问者模式