访问者模式(visitor pattern):封装一些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
通俗的定义:在每个自定义对象中预定义一个Accept(请求访问)方法,这个方法会以对象为参数,调用Visitor(访问者)对象的visit方法来操作这个对象。
类图及定义
抽象访问者(visitor):声明一个或多个访问操作,形成所有元素都要是实现的接口。
具体访问者(concrete visitor):实现抽象访问者所声明的接口。
抽象节点(element):声明一个接受操作,接受一个访问者对象作为参数。
具体节点(concrete element):实现了抽象元素所规定的的接受操作。
结构对象(object structure):遍历结构中的所有对象,类似set、list等。
访问者模式的缺点
- 破坏了封装(就是clean code中的A.getB().getC())
- 增加节点困难(其实很多设计师反对使用)。
//抽象访问者
public abstract class Visitor {
public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}
//具体访问者1
public class ConcreteVisitor1 extends Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().getSimpleName() + "被"
+ this.getClass().getSimpleName() + "访问");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName() + "被"
+ this.getClass().getSimpleName() + "访问");
}
}
//具体访问者2
public class ConcreteVisitor2 extends Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().getSimpleName() + "被"
+ this.getClass().getSimpleName() + "访问");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName() + "被"
+ this.getClass().getSimpleName() + "访问");
}
}
//抽象节点
public abstract class Element {
public abstract void accept(Visitor visitor);
}
//具体节点。每个自定义对象中预定义一个Accept(请求访问)方法,这个方法会以对象为参数,
//调用Visitor(访问者)对象的visit方法来操作这个对象。
public class ConcreteElementA extends Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
}
public class ConcreteElementB extends Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
}
public class VisitorClient {
public static void main(String[] args) {
ObjectStructure o = new ObjectStructure();
o.attach(new ConcreteElementA());
o.attach(new ConcreteElementB());
ConcreteVisitor1 visitor1 = new ConcreteVisitor1();
ConcreteVisitor2 visitor2 = new ConcreteVisitor2();
o.accept(visitor1);
o.accept(visitor2);
}
}