一句话总结
访问者不同,结果不同
内容
不同访问者实现对相同数据集的不同的操作
场景
kpi考核:考核标准是相对稳定,但CEO和CTO的看重员工的点是不同的。
餐厅:餐厅的菜单和就餐方式是相对稳定的,但取就餐人员是每天变化的。
类图
代码示例
// 抽象元素
public interface IElement {
void accept(IVisitor visitor);
}
// 具体元素
public class ConcreteElementA implements IElement {
public void accept(IVisitor visitor) {
visitor.visit(this);
}
public String operationA() {
return this.getClass().getSimpleName();
}
}
// 具体元素
public class ConcreteElementB implements IElement {
public void accept(IVisitor visitor) {
visitor.visit(this);
}
public int operationB() {
return new Random().nextInt(100);
}
}
// 结构对象
public class ObjectStructure {
private List<IElement> list = new ArrayList<IElement>();
{
this.list.add(new ConcreteElementA());
this.list.add(new ConcreteElementB());
}
public void accept(IVisitor visitor) {
for (IElement element : this.list) {
element.accept(visitor);
}
}
}
// 抽象访问者
public interface IVisitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
// 具体访问者
public class ConcreteVisitorA implements IVisitor {
public void visit(ConcreteElementA element) {
String result = element.operationA();
System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
}
public void visit(ConcreteElementB element) {
int result = element.operationB();
System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
}
}
// 具体访问者
public class ConcreteVisitorB implements IVisitor {
public void visit(ConcreteElementA element) {
String result = element.operationA();
System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
}
public void visit(ConcreteElementB element) {
int result = element.operationB();
System.out.println("result from " + element.getClass().getSimpleName() + ": " + result);
}
}
public class Test {
public static void main(String[] args) {
ObjectStructure collection = new ObjectStructure();
System.out.println("ConcreteVisitorA handle elements:");
IVisitor visitorA = new ConcreteVisitorA();
collection.accept(visitorA);
System.out.println("------------------------------------");
System.out.println("ConcreteVisitorB handle elements:");
IVisitor visitorB = new ConcreteVisitorB();
collection.accept(visitorB);
}
}
运行结果
访问者模式中的两次动态分派
静态分派和动态分派
静态类型是List即变量的生命类型,实际类型是对象的类型
List str = new ArrayList()
静态分派指根据静态类型进行分派,在编译时期完成如重载方法的分配。
动态分派指根据实际类型进行分派,在运行时期完成如多态。
访问者模式中的两次动态分派
第一次分配
根据element的具体对象来决定调用具体元素对象的方法。
public void accept(IVisitor visitor) {
for (IElement element : this.list) {
element.accept(visitor);
}
}
第二次分配
根据IVisitor的具体对象来确定调用哪个IVisitor具体实现方法。
public void accept(IVisitor visitor) {
visitor.visit(this);
}