一、定义

Visitor表示一个被执行于某对象结构(object structure)中的各元素的操作。访问者模式使你在不改变各元素的类的前提下定义一个作用于这些元素的新操作

二、类图表示

访问者模式

三、实现

1、Element

package pattern.behavioral.visitor;

public abstract class Element {

	public abstract void accept(Visitor visitor);
}


package pattern.behavioral.visitor;

public class ConcreteElementA extends Element {

	@Override
	public void accept(Visitor visitor) {
		visitor.visitConcreteElementA(this);
	}
	
	public void operationA(){
		
	}
}


package pattern.behavioral.visitor;

public class ConcreteElementB extends Element {

	@Override
	public void accept(Visitor visitor) {
		visitor.visitConcreteElementB(this);
	}

	public void operationB(){
		
	}
}

2、ObjectStructure

package pattern.behavioral.visitor;

import java.util.ArrayList;
import java.util.List;

public class ObjectStructure {

	private List<Element> elements = new ArrayList<>();
	
	public void attach(Element element){
		elements.add(element);
	}
	
	public void detach(Element element){
		elements.remove(element);
	}
	
	public void accept(Visitor visitor){
		for(Element element : elements){
			element.accept(visitor);
		}
	}
}

3、Visitor

package pattern.behavioral.visitor;

public abstract class Visitor {

	public abstract void visitConcreteElementA(ConcreteElementA element);
	
	public abstract void visitConcreteElementB(ConcreteElementB element);
}


package pattern.behavioral.visitor;

public class ConcreteVisitorA extends Visitor {

	@Override
	public void visitConcreteElementA(ConcreteElementA element) {
		System.out.println("ElementA visited by " + this.getClass().getSimpleName());
	}

	@Override
	public void visitConcreteElementB(ConcreteElementB element) {
		System.out.println("ElementB visited by " + this.getClass().getSimpleName());
	}

}


package pattern.behavioral.visitor;

public class ConcreteVisitorB extends Visitor {

	@Override
	public void visitConcreteElementA(ConcreteElementA element) {
		System.out.println("ElementA visited by " + this.getClass().getSimpleName());
	}

	@Override
	public void visitConcreteElementB(ConcreteElementB element) {
		System.out.println("ElementB visited by " + this.getClass().getSimpleName());
	}

}

四、使用

package pattern.behavioral.visitor;

public class Client {

	public static void main(String[] args) {
		//object structure has two elements
		ObjectStructure os = new ObjectStructure();
		os.attach(new ConcreteElementA());
		os.attach(new ConcreteElementB());
		
		Visitor visitorA = new ConcreteVisitorA();
		Visitor visitorB = new ConcreteVisitorB();
		
		os.accept(visitorA);
		os.accept(visitorB);
	}
}
  • 程序输出:
ElementA visited by ConcreteVisitorA
ElementB visited by ConcreteVisitorA
ElementA visited by ConcreteVisitorB
ElementB visited by ConcreteVisitorB

五、适用场合

  • 如果一个对象结构中包含很多不同类型对象,它们有不同的接口,而想对这些不同的对象实施一些依赖于具体类的操作的时候

  • 如果一个对象结构的类很少改变,但经常需要在此结构上定义新的操作时(如果对象结构的类会经常改变,那么最好还是在这些类中定义操作比较好,因为改变对象结构类时需要重新定义对所有访问者的接口,这可能需要很大的代价)

  • 需要对一个对象结构中的元素进行很多不同且不相关的操作,而又想避免这些操作与这些元素的类关联起来。访问者模式可以将相关的操作集中起来,单独定义在一个类中。当该对象结构被很多应用共享时,此模式能让每个应用仅包含需要用到的操作。