访问者模式:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
访问者模式适用于数据结构相对稳定的系统。它把数据结构和作用于结构上的操作之间的耦合解开,使得操作集合可以相对自由地演化。
访问者模式的目的是要把处理从数据结构分离出来。如果系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较适合的,因为访问者模式使得算法操作的增加变的容易。
优点:增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。
缺点:增加新的数据结构变得困难。
一个接口定义访问者,即状态,接口定义多个方法,每个方法接收一个具体的元素,即具体元素有几个则定义几个方法,每个实现类实现一种状态。一个接口定义元素,定义一个接收访问者的方法,这个元素结构不改变,元素的具体实现接收访问者,调用访问者的方法完成状态的实现。一个调用元素的操作类,元素集合作为属性,一个方法接收访问者,在方法中遍历集合去调用访问者。
/**
* 访问者
*/
public interface Visitor {
void visitConcreteElementA(ConcreteElementA concreteElementA); //访问A元素
void visitConcreteElementB(ConcreteElementB concreteElementB); //访问B元素
}
/**
* 第一种访问者的操作
*/
public class ConcreteVisitorA implements Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println("A元素进行第一种操作");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println("B元素进行第一种操作");
}
}
/**
* 第二种访问者的操作
*/
public class ConcreteVisitorB implements Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println("A元素进行第二种操作");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println("B元素进行第二种操作");
}
}
/**
* 不会改变的数据结构
*/
public interface Element {
void accept(Visitor visitor);
}
/**
* 具体元素A
*/
public class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
}
/**
* 具体元素B
*/
public class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
}
/**
* 访问元素
*/
public class ObjectStructure {
private List<Element> list = new ArrayList<>();
public void add(Element element){
list.add(element);
}
public void remove(Element element){
list.remove(element);
}
public void accept(Visitor visitor){
for (Element element : list) {
element.accept(visitor);
}
}
}
public class Main {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
ConcreteElementA concreteElementA = new ConcreteElementA();
ConcreteElementB concreteElementB = new ConcreteElementB();
objectStructure.add(concreteElementA);
objectStructure.add(concreteElementB);
objectStructure.accept(new ConcreteVisitorA()); //A元素进行第一种操作 B元素进行第一种操作
objectStructure.accept(new ConcreteVisitorB()); //A元素进行第二种操作 B元素进行第二种操作
}
}