1.使用场景:
在一个集合中有一些不同的子类对象,需要分别对这些子类对象做处理。常常应用于XML文档的解析、编辑器的解析等。
2.UML表示:
2.1 Visitor(抽象访问者):抽象访问者为对象结构中每一个具体元素类ConcreteElement声明一个访问操作,从这个操作的名称或参数类型可以清楚知道需要访问的具体元素的类型,具体访问者则需要实现这些操作方法,定义对这些元素的访问操作。
2.2 ConcreteVisitor(具体访问者):具体访问者实现了抽象访问者声明的方法,每一个操作作用于访问对象结构中一种类型的元素。
2.3 Element(抽象元素):一般是一个抽象类或接口,定义一个Accept方法,该方法通常以一个抽象访问者作为参数。
2.4 ConcreteElement(具体元素):具体元素实现了Accept方法,在Accept方法中调用访问者的访问方法以便完成一个元素的操作。
2.5 ObjectStructure(对象结构):对象结构是一个元素的集合,用于存放元素对象,且提供便利其内部元素的方法。
具体的UML示意图如下:
3.代码实现
参考了一个例子:http://www.cnblogs.com/chenpi/p/5222390.html
定义一个visitor接口:
public interface Visitor {
/**
*
* @author lsj
* @date 2018/2/16 16:05
* @param [wheel]
* @return void
*/
void visit(Wheel wheel);
/**
*
* @author lsj
* @date 2018/2/16 16:06
* @param [engine]
* @return void
*/
void visit(Engine engine);
/**
*
* @author lsj
* @date 2018/2/16 16:06
* @param [body]
* @return void
*/
void visit(Body body);
/**
*
* @author lsj
* @date 2018/2/16 16:06
* @param [car]
* @return void
*/
void visit(Car car);
}
具体的访问者类,定义一些行为:
public class PrintVisitor implements Visitor {
@Override
public void visit(Wheel wheel) {
System.out.println("轮子");
}
@Override
public void visit(Engine engine) {
System.out.println("引擎");
}
@Override
public void visit(Body body) {
System.out.println("车身");
}
@Override
public void visit(Car car) {
System.out.println("整车");
}
}
定义Visitable接口:
public interface Visitable {
public void accept(Visitor visitor);
}
定义各部件类:
public class Engine implements Visitable {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class Body implements Visitable {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class Wheel implements Visitable {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class Car implements Visitable {
private Engine engine=new Engine();
private Body body=new Body();
private Wheel wheel=new Wheel();
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
engine.accept(visitor);
body.accept(visitor);
wheel.accept(visitor);
}
}
简单的测试类:
public class Client {
public static void main(String[] args) {
Car car=new Car();
Visitor visitor=new PrintVisitor();
car.accept(visitor);
}
}
4.总结
通过上面的例子,我们可以看出,一旦操作逻辑发生改变,我们只要更改PrintVisitor类中的代码即可,与此同时,一旦需要新添加一些“零件”,例如再添加一个“尾翼”类,只需要改变访问者接口即可。
代码地址:
https://github.com/memoryexplosion/design_pattern_review/tree/master/src/java/visitor