访问者模式(Visitor Pattern)详解
文章目录
- 1. 访问者模式概述
- 1.1 定义
- 1.2 基本思想
- 2. 访问者模式的结构
- 3. 访问者模式的UML类图
- 4. 访问者模式的工作原理
- 5. Java实现示例
- 5.1 基本实现示例
- 5.2 访问者模式处理复杂对象层次结构
- 5.3 访问者模式在文件系统中的应用
- 6. 访问者模式的优缺点
- 6.1 优点
- 6.2 缺点
- 7. 访问者模式的适用场景
- 8. 访问者模式在框架中的应用
- 8.1 Java的反射API
- 8.2 Java ASM库
- 8.3 Spring框架中的BeanDefinitionVisitor
- 9. 访问者模式与其他设计模式的区别与联系
- 9.1 访问者模式与策略模式
- 9.2 访问者模式与组合模式
- 9.3 访问者模式与命令模式
- 10. 实战案例:电商订单处理系统
- 11. 总结
1. 访问者模式概述
1.1 定义
访问者模式是一种行为型设计模式,它允许在不改变各元素类的前提下定义作用于这些元素的新操作。访问者模式通过将操作与对象结构分离,使得我们可以在不修改对象结构的情况下向现有对象结构添加新的操作。
1.2 基本思想
访问者模式的核心思想是:
- 将数据结构与数据操作分离
- 针对不同的元素类型,访问者可以执行不同的操作
- 在不修改已有类的情况下,通过添加新的访问者实现对元素的新操作
2. 访问者模式的结构
访问者模式包含以下角色:
- 抽象访问者(Visitor):声明了一组访问方法,用于访问不同类型的具体元素
- 具体访问者(ConcreteVisitor):实现抽象访问者接口中声明的方法,为不同类型的元素提供具体操作实现
- 抽象元素(Element):声明一个接受访问者的方法(accept),以供访问者访问
- 具体元素(ConcreteElement):实现抽象元素接口,实现accept方法接受访问者访问
- 对象结构(ObjectStructure):包含元素集合,可以提供让访问者遍历其内部元素的方法
3. 访问者模式的UML类图
┌─────────────────┐ ┌─────────────────┐
│ ObjectStructure │ │ <<interface>> │
├─────────────────┤ │ Element │
│ +elements │<>────────├─────────────────┤
│ +accept(Visitor)│ │ +accept(Visitor)│
└─────────────────┘ └────────┬────────┘│ ││ ││ ┌───────────┴───────────┐│ │ ││ ┌─────────▼────────┐ ┌──────────▼─────────┐│ │ ConcreteElementA│ │ ConcreteElementB ││ ├──────────────────┤ ├────────────────────┤│ │+accept(Visitor) │ │+accept(Visitor) ││ └──────────────────┘ └────────────────────┘│ │ ││ │ ││ ▼ ▼│ "visitor.visitA(this)" "visitor.visitB(this)"│││ ┌─────────────────────┐└─────>│ <<interface>> ││ Visitor │├─────────────────────┤│+visitA(ElementA) ││+visitB(ElementB) │└──────────┬──────────┘││┌─────────────┴────────────┐│ │
┌────────────▼────────────┐ ┌──────────▼────────────┐
│ ConcreteVisitor1 │ │ ConcreteVisitor2 │
├─────────────────────────┤ ├─────────────────────────┤
│+visitA(ElementA) │ │+visitA(ElementA) │
│+visitB(ElementB) │ │+visitB(ElementB) │
└─────────────────────────┘ └─────────────────────────┘
4. 访问者模式的工作原理
- 当需要对一个对象结构中的元素进行操作时,访问者模式可以在不修改元素类的前提下实现新功能
- 每个具体元素都实现accept方法,该方法通过调用访问者对象的对应方法来实现功能
- 具体访问者针对每种具体元素类型实现相应的访问方法
- 在访问者模式中,双重分派是一个核心概念:
- 第一次分派:根据元素的实际类型选择调用哪个accept方法
- 第二次分派:在accept方法内部,根据访问者的实际类型选择调用哪个visit方法
5. Java实现示例
5.1 基本实现示例
下面是一个简单的访问者模式实现示例,假设我们有一个简单的计算机部件系统:
// 抽象访问者
interface ComputerPartVisitor {void visit(Computer computer);void visit(Mouse mouse);void visit(Keyboard keyboard);void visit(Monitor monitor);
}// 抽象元素
interface ComputerPart {void accept(ComputerPartVisitor visitor);
}// 具体元素类:鼠标
class Mouse implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor visitor) {visitor.visit(this);}
}// 具体元素类:键盘
class Keyboard implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor visitor) {visitor.visit(this);}
}// 具体元素类:显示器
class Monitor implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor visitor) {visitor.visit(this);}
}// 具体元素类:计算机(复合元素)
class Computer implements ComputerPart {ComputerPart[] parts;public Computer() {parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};}@Overridepublic void accept(ComputerPartVisitor visitor) {for (ComputerPart part : parts) {part.accept(visitor);}visitor.visit(this);}
}// 具体访问者:显示访问者
class ComputerPartDisplayVisitor implements ComputerPartVisitor {@Overridepublic void visit(Computer computer) {System.out.println("展示计算机。");}@Overridepublic void visit(Mouse mouse) {System.out.println("展示鼠标。");}@Overridepublic void visit(Keyboard keyboard) {System.out.println("展示键盘。");}@Overridepublic void visit(Monitor monitor) {System.out.println("展示显示器。");}
}// 具体访问者:维护访问者
class ComputerPartMaintainVisitor implements ComputerPartVisitor {@Overridepublic void visit(Computer computer) {System.out.println("维护计算机。");}@Overridepublic void visit(Mouse mouse) {System.out.println("清洁鼠标。");}@Overridepublic void visit(Keyboard keyboard) {System.out.println("清洁并检查键盘按键。");}@Overridepublic void visit(Monitor monitor) {System.out.println("校准并清洁显示器屏幕。");}
}// 客户端
public class ComputerPartClient {public static void main(String[] args) {ComputerPart computer = new Computer();System.out.println("展示操作:");computer.accept(new ComputerPartDisplayVisitor());System.out.println("\n维护操作:");computer.accept(new ComputerPartMaintainVisitor());}
}
5.2 访问者模式处理复杂对象层次结构
下面是一个处理不同形状的访问者模式示例:
// 形状接口 - 抽象元素
interface Shape {void accept(ShapeVisitor visitor);
}// 圆形 - 具体元素
class Circle implements Shape {private double radius;public Circle(double radius) {this.radius = radius;}public double getRadius() {return radius;}@Overridepublic void accept(ShapeVisitor visitor) {visitor.visit(this);}
}// 矩形 - 具体元素
class Rectangle implements Shape {private double width;private double height;public Rectangle(double width, double height) {this.width = width;this.height = height;}public double getWidth() {return width;}public double getHeight() {return height;}@Overridepublic void accept(ShapeVisitor visitor) {visitor.visit(this);}
}// 三角形 - 具体元素
class Triangle implements Shape {private double sideA;private double sideB;private double sideC;public Triangle(double sideA, double sideB, double sideC) {this.sideA = sideA;this.sideB = sideB;this.sideC = sideC;}public double getSideA() {return sideA;