前言
访问者模式的目的是让一个访问者能够在不改变被访问者类的情况下,访问并操作被访问者的内部结构。 这种模式通常用于对一个对象结构进行遍历,并在遍历过程中对每个元素执行不同的操作。访问者模式可以让你在不改变对象结构的情况下,定义新的操作。
角色
- Visitor:访问者接口,定义了访问者可以访问哪些元素,并定义了每个元素的 accept 方法。
- ConcreteVisitor:具体的访问者类,实现了 Visitor 接口中定义的方法。
- Element:元素接口,定义了 accept 方法,以便访问者能够访问它。
- ConcreteElement:具体的元素类,实现了 Element 接口中定义的方法
示例
假设有一个图形绘制程序,其中包含若干个不同类型的图形对象,例如矩形、圆形和三角形。为了支持对这些图形对象进行不同的操作,我们可以使用访问者模式。
Visitor 接口
public interface Visitor {
void visitRectangle(Rectangle rectangle);
void visitCircle(Circle circle);
void visitTriangle(Triangle triangle);
}
Element 接口
public interface Element {
void accept(Visitor visitor);
}
矩形类
public class Rectangle implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visitRectangle(this);
}
}
圆形类
public class Circle implements Element{
@Override
public void accept(Visitor visitor) {
visitor.visitCircle(this);
}
}
三角形类
public class Triangle implements Element{
@Override
public void accept(Visitor visitor) {
visitor.visitTriangle(this);
}
}
具体访问者类
public class PerimeterCalculator implements Visitor {
@Override
public void visitRectangle(Rectangle rectangle) {
System.out.println("计算矩形的周长....");
}
@Override
public void visitCircle(Circle circle) {
System.out.println("计算圆形的周长....");
}
@Override
public void visitTriangle(Triangle triangle) {
System.out.println("计算三角形的周长....");
}
}
测试
public class Demo {
public static void main(String[] args) {
List<Element> elements = new ArrayList<>();
// 创建并添加不同类型的图形对象
elements.add(new Rectangle());
elements.add(new Circle());
elements.add(new Triangle());
// 创建计算图形周长的访问者
PerimeterCalculator calculator = new PerimeterCalculator();
// 遍历图形列表,对每个图形调用 accept 方法
for (Element element : elements) {
element.accept(calculator);
}
}
}
输出
优缺点
优点
- 在不改变被访问者的情况下,增加新的操作。访问者模式可以让你在不改变对象结构的情况下,定义新的操作。这样就能够很方便地扩展程序的功能。
- 访问者模式可以让你把复杂的操作分解成若干个简单的操作,使得程序更容易维护和扩展
缺点
- 访问者模式会使程序变得复杂。因为访问者模式把复杂的操作分解成若干个简单的操作,所以会使程序变得更复杂。
- 访问者模式要求访问者和被访问者之间有一个约定,即访问者需要知道被访问者的内部结构。这样会使访问者与被访问者之间紧密地耦合在一起,不利于程序的扩展和维护。