visitor访问者模式的意图,在《设计模式》里这样描述:“表示一个作用于某个对象结构中的各元素的操作。它使可以在不改变各元素的类的前提下定义作用于这些元素的新操作。”。就是说:在坚持“开闭原则”的情况下,访问者可以用来扩展一个现有的类层次结构来实现新的行为。更通俗的讲,如果不愿意修改类层次结构内部代码或者类层次结构的代码难以修改的情况下,如果该类层次结构在设计实现时使用了visitor访问者模式,那么可以实现“在不修改类层次结构代码的前提下”进行扩展。
但是visitor访问者模式是一个有争议的模式,在《Design Paterns Java Workbook》(作者Steven John Metsker)里提到了三种代替方案。
《Software Architecture Design Patterns in Java》中的例子:
public interface VisitorInterface {
public void visit(NonCaliforniaOrder nco);
public void visit(CaliforniaOrder co);
public void visit(OverseasOrder oo);
}
public class OrderVisitor implements VisitorInterface {
private double orderTotal;
public OrderVisitor() {
}
public void visit(NonCaliforniaOrder inp_order) {
orderTotal = orderTotal + inp_order.getOrderAmount();
}
public void visit(CaliforniaOrder inp_order) {
orderTotal = orderTotal + inp_order.getOrderAmount() +
inp_order.getAdditionalTax();
}
public void visit(OverseasOrder inp_order) {
orderTotal = orderTotal + inp_order.getOrderAmount() +
inp_order.getAdditionalSH();
}
public double getOrderTotal() {
return orderTotal;
}
}
public class OverseasOrder implements Order {
private double orderAmount;
private double additionalSH;
public OverseasOrder() {
}
public OverseasOrder(double inp_orderAmount,
double inp_additionalSH) {
orderAmount = inp_orderAmount;
additionalSH = inp_additionalSH;
}
public double getOrderAmount() {
return orderAmount;
}
public double getAdditionalSH() {
return additionalSH;
}
public void accept(OrderVisitor v) {
v.visit(this);
}
}
public class CaliforniaOrder implements Order {
private double orderAmount;
private double additionalTax;
public CaliforniaOrder() {
}
public CaliforniaOrder(double inp_orderAmount,
double inp_additionalTax) {
orderAmount = inp_orderAmount;
additionalTax = inp_additionalTax;
}
public double getOrderAmount() {
return orderAmount;
}
public double getAdditionalTax() {
return additionalTax;
}
public void accept(OrderVisitor v) {
v.visit(this);
}
}
public class NonCaliforniaOrder implements Order {
private double orderAmount;
public NonCaliforniaOrder() {
}
public NonCaliforniaOrder(double inp_orderAmount) {
orderAmount = inp_orderAmount;
}
public double getOrderAmount() {
return orderAmount;
}
public void accept(OrderVisitor v) {
v.visit(this);
}
}