一、什么是访问者模式?
访问者模式(Visitor)定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变现有各元素的类的前提下定义作用于这些元素的新操作。
类型:行为型模式(Behavioral)
顺口溜: 中访策备迭 观模命状职解
二、访问者模式UML
三、JAVA代码实现
package com.amosli.dp.behavior.visitor;
/**
* VISITOR PATTERN
*
* @author amosli
*
*/
public class Client {
public static void main(String[] args) {
ObjectStructure obj = new ObjectStructure();
obj.attach(new ConcreteElementA());
obj.attach(new ConcreteElementB());
obj.accept(new ConcreteVisitorA());
obj.accept(new ConcreteVisitorB());
}
}
package com.amosli.dp.behavior.visitor;
public abstract class Element {
public abstract void accept(Visitor visitor);
}
package com.amosli.dp.behavior.visitor;
public abstract class Visitor {
public abstract void visitConcreteElementA(ConcreteElementA elementA);
public abstract void visitConcreteElementB(ConcreteElementB elementB);
}
package com.amosli.dp.behavior.visitor;
import java.util.ArrayList;
import java.util.List;
public class ObjectStructure {
private List<Element> list = new ArrayList<Element>();
public void attach(Element element) {
list.add(element);
}
public void detach(Element element) {
list.remove(element);
}
public void accept(Visitor visitor){
for (Element element : list) {
element.accept(visitor);
}
}
}
package com.amosli.dp.behavior.visitor;
public class ConcreteElementA extends Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
public void methodA() {
}
}
package com.amosli.dp.behavior.visitor;
public class ConcreteElementB extends Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
public void methodB() {
}
}
package com.amosli.dp.behavior.visitor;
public class ConcreteVisitorA extends Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA elementA) {
System.out.println(elementA.getClass().getName() + "被" + this.getClass().getName()+" 调用");
}
@Override
public void visitConcreteElementB(ConcreteElementB elementB) {
System.out.println(elementB.getClass().getName() + "被" + this.getClass().getName()+" 调用");
}
}
package com.amosli.dp.behavior.visitor;
public class ConcreteVisitorB extends Visitor{
@Override
public void visitConcreteElementA(ConcreteElementA elementA) {
System.out.println(elementA.getClass().getName() + "被" + this.getClass().getName()+" 调用");
}
@Override
public void visitConcreteElementB(ConcreteElementB elementB) {
System.out.println(elementB.getClass().getName() + "被" + this.getClass().getName()+" 调用");
}
}
根据对象的类型而对方法进行的选择,就是分派(Dispatch),分派(Dispatch)又分为两种,即静态分派和动态分派。
静态分派(Static Dispatch)发生在编译时期,分派根据静态类型信息发生。静态分派对于我们来说并不陌生,方法重载就是静态分派。
动态分派(Dynamic Dispatch)发生在运行时期,动态分派动态地置换掉某个方法。
四、使用场景
1、 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2、 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor模式使得你可以将相关的操作集中起来 定义在一个类中。
3、 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
4、定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
五、源码地址
本系列文章源码地址,https://github.com/amosli/dp 欢迎Fork & Star !!