1、模式介绍:
访问者模式是一种行为设计模式,其主要目的是在不改变已有类的前提下,定义作用于这些类对象结构中的新功能。它将数据结构与数据操作分离,使得操作集合可以独立变化。
2、应用场景:
当一个数据结构包含许多不同类型的对象,而你希望对这些对象实施一些依赖其具体类型的操作时,可以使用访问者模式。例如,编译器中对抽象语法树(AST)的不同节点进行不同的操作。
当需要在不改变类的前提下,添加新的操作时,访问者模式可以帮助避免修改现有代码,而只需新增访问者类即可。
当对象结构中的元素类很少改变,但经常需要在此结构上定义新的操作时,访问者模式提供了一种灵活的方式。
3、优点:
符合单一职责原则:将相关行为封装在一起,使得代码易于理解和维护。
扩展性良好:可以通过增加新的访问者类,实现对已有代码的功能扩展,而无需修改现有代码。
分离数据结构和算法:可以在不修改原有数据结构的情况下,增加新的操作。
4、缺点:
增加新的元素类比较困难,需要修改所有的访问者类。
具体元素暴露,增加了对象结构的复杂度。
5、代码示例:
/**
* 元素接口
*/
public interface Element {
void accept(Visitor visitor);
}
/**
* 具体元素实现类A
*/
public class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
/**
* 具体元素实现类B
*/
public class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
/**
* 访问者接口
*/
public interface Visitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
/**
* 具体的访问者实现
*/
public class ConcreteVisitor implements Visitor {
@Override
public void visit(ConcreteElementA element) {
System.out.println("Visitor is visiting ConcreteElementA");
// 对ConcreteElementA的具体操作
}
@Override
public void visit(ConcreteElementB element) {
System.out.println("Visitor is visiting ConcreteElementB");
// 对ConcreteElementB的具体操作
}
}
/**
* 对象结构类,可以包含多种不同的元素对象
*/
public class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void attach(Element element) {
elements.add(element);
}
public void detach(Element element) {
elements.remove(element);
}
public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
/**
* 应用
*/
public class VisitorClient {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new ConcreteElementA());
objectStructure.attach(new ConcreteElementB());
Visitor visitor = new ConcreteVisitor();
objectStructure.accept(visitor);
}
}
6、示例讲解:
Visitor
定义了访问者的接口,包括访问不同具体元素的方法。ConcreteVisitor
是具体的访问者实现,实现了对不同具体元素的访问操作。Element
定义了元素的接口,包括接受访问者访问的方法 accept()
。ConcreteElementA
和 ConcreteElementB
是具体的元素实现类,实现了 Element
接口的 accept()
方法,并在其中调用访问者的访问方法。ObjectStructure
定义了对象结构,可以包含多种不同的元素对象,并提供了接受访问者的方法 accept()
,用于遍历其中的元素并调用它们的 accept()
方法。
在 main
方法中,创建了一个具体的对象结构 ObjectStructure
,并向其中添加了 ConcreteElementA
和 ConcreteElementB
。然后创建了一个具体的访问者 ConcreteVisitor
,并调用对象结构的 accept()
方法,传入访问者,从而实现对元素的访问。