定义:
-
封装一作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
访问者模式的通用类图
/*
* 抽象元素,声明接受哪一类访问者访问,程序上是通过accept方法 中的参数来定义的
* */
public abstract class Element {
public abstract void doSomething();
// 允许哪个访问者访问
public abstract void accept(IVisitor visitor);
}
public class ConcreteElementOne extends Element {
@Override
public void doSomething() {
// TODO Auto-generated method stub
}
@Override
public void accept(IVisitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
}
public class ConcreteElementTwo extends Element {
@Override
public void doSomething() {
// TODO Auto-generated method stub
}
@Override
public void accept(IVisitor visitor) {
// TODO Auto-generated method stub
visitor.visit(this);
}
}
public interface IVisitor {
// 抽象的访问者,定义可以访问哪些对象
public void visit(ConcreteElementOne concreteElementOne);
public void visit(ConcreteElementTwo concreteElementTwo);
}
public class Visitor implements IVisitor {
// 定义具体的访问者,访问对应的元素
@Override
public void visit(ConcreteElementOne concreteElementOne) {
// TODO Auto-generated method stub
concreteElementOne.doSomething();
}
@Override
public void visit(ConcreteElementTwo concreteElementTwo) {
// TODO Auto-generated method stub
concreteElementTwo.doSomething();
}
}
/*
* 定义结构对象,产生不同的元素对象
* */
public class ObjectStruture {
public static Element createElement() {
Random rand = new Random();
if (rand.nextInt(100) > 50) {
return new ConcreteElementOne();
} else {
return new ConcreteElementTwo();
}
}
}
public class Client {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
// 获取元素对象
Element element = ObjectStruture.createElement();
// 接受访问者访问
element.accept(new Visitor());
}
}
}
优点:
- 符合单一职责原则:具体角色有Element抽象类的两个子类进行数据的加载,而Visitor类则负责报表的呈现,两个不同的职责明确地分离开,各自演绎。
- 优秀的拓展性:增加数据的不同表现形式只需要增加一个visitor即可
- 灵活性非常高:通过不同的visitor可以展示出不同的数据形式
缺点:
- 具体元素对访问者公布细节
- 具体元素变更比较困难
- 违背了依赖倒置原则,访问者依赖的是具体的元素,而不是抽象的元素,拓展较难

