访问者模式:表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
Visitor类,为该对象结构中ConcreteVisitor的每一个类声明一个Visit操作。访问者接口为使用不同算法的子类声明访问操作。
public abstract class Visitor {
public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}
ConcreteVisitor1和ConcreteVisitor2类,具体访问者。每个操作实现这种算法(1或2)的一部分。
public class ConcreteVisitor1 extends Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA.getClass().getSimpleName()+"被"+this.getClass().getSimpleName() + "访问");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB.getClass().getSimpleName()+"被"+this.getClass().getSimpleName() + "访问");
}
}
public class ConcreteVisitor1 extends Visitor {
//代码与上类类似
}
Element类,定义一个accept操作接口,它以一个访问者为参数
public abstract class Element {
public abstract void accept(Visitor visitor);
}
ConcreteElementA和ConcreteElementB类,具体元素,实现accept操作。
public class ConcreteElementA extends Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
public void OperationA(){} ---其它的相关方法
}
public class ConcreteElementB extends Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
public void OperationB(){} ---其它的相关方法
}
ObjectStructure类,能枚举它的元素,提供一个高层接口以允许访问者访问它的元素
public class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void addElement(Element element) {
elements.add(element);
}
public void visit(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
客户端代码
public static void main(String[] args) {
ObjectStructure oStructure = new ObjectStructure();
oStructure.addElement(new ConcreteElementA());
oStructure.addElement(new ConcreteElementB());
ConcreteVisitor1 visitor1 = new ConcreteVisitor1();
ConcreteVisitor2 visitor2 = new ConcreteVisitor2();
oStructure.visit(visitor1);
System.out.println("-------------------");
oStructure.visit(visitor2);
}
ConcreteElementA被ConcreteVisitor1访问
ConcreteElementB被ConcreteVisitor1访问
-------------------
ConcreteElementA被ConcreteVisitor2访问
ConcreteElementB被ConcreteVisitor2访问
举一个例子来理解该模式:人分为男人和女人,男人和女人在成功或恋爱时的反应不同。
这里人的属性男人和女人可以当成ConcreteElement
成功和恋爱或其它的状态可以当成ConcreteVisitor,它们去访问元素(男人或女人)的具体反应。
People抽象类
public abstract class Person {
public abstract void accept(Action visitor);
}
状态抽象类
public abstract class Action {
public abstract void getManConclusion(Person man);
public abstract void getWomanConclusion(Person woman);
}
Man类和Woman类
public class Man extends Person {
@Override
public void accept(Action visitor) {
// TODO Auto-generated method stub
visitor.getManConclusion(this);
}
}
public class Woman extends Person {
@Override
public void accept(Action visitor) {
// TODO Auto-generated method stub
visitor.getWomanConclusion(this);
}
}
状态的子类,Success类(ConcreteVisitor),其余状态(恋爱等)和Success类代码类似不进行列举。
public class Success extends Action {
@Override
public void getManConclusion(Person man) {
System.out.println(man.getClass().getSimpleName() + this.getClass().getSimpleName() + "高调");
}
@Override
public void getWomanConclusion(Person woman) {
System.out.println(woman.getClass().getSimpleName() + this.getClass().getSimpleName() + "低调");
}
}
对象结构类
public class ObjectStructure {
private List<Person> persons = new ArrayList<>();
public void addPerson(Person person) {
persons.add(person);
}
public void display(Action visitor) {
for (Person person : persons) {
person.accept(visitor);
}
}
}
客户端测试
public static void main(String[] args) {
// TODO Auto-generated method stub
ObjectStructure oStructure = new ObjectStructure();
oStructure.addPerson(new Man());
oStructure.addPerson(new Woman());
Success success = new Success();
oStructure.display(success);
}
ManSuccess高调
WomanSuccess低调
访问者模式只适用于数据结构相对稳定的系统,例如上面的示例中人只分为男人和女人两个类型,如果能有多个性别,“状态”类中的抽象方法就不可能稳定,每增加一个类别,就需要在状态类和它的下属类中都增加一个方法。
访问者模式把数据结构和作用于结构之上的操作之间的耦合解开,使得操作集合可以相对自由地演化。访问者模式的目的是要把处理从数据结构分离出来,如果系统有稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是合适的,访问者模式使算法操作的增加变得容易。