当前位置: 首页 > news >正文

访问者模式(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. 访问者模式的工作原理

  1. 当需要对一个对象结构中的元素进行操作时,访问者模式可以在不修改元素类的前提下实现新功能
  2. 每个具体元素都实现accept方法,该方法通过调用访问者对象的对应方法来实现功能
  3. 具体访问者针对每种具体元素类型实现相应的访问方法
  4. 在访问者模式中,双重分派是一个核心概念:
    • 第一次分派:根据元素的实际类型选择调用哪个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;

相关文章:

  • excel大表导入数据库
  • RAG 2.0 深入解读
  • OSPF不规则区域划分
  • 从代码学习深度学习 - 语义分割和数据集 PyTorch版
  • 部署RocketMQ
  • 垃圾对象回收
  • 2025年5月15日前 免费考试了! Oracle AI 矢量搜索专业​​认证
  • 青藏高原东北部祁连山地区250m分辨率多年冻土空间分带指数图(2023)
  • [虚幻官方教程学习笔记]深入理解实时渲染(An In-Depth Look at Real-Time Rendering)
  • LeetCode热题100--240.搜索二维矩阵--中等
  • kotlin flow防抖
  • 聊一聊接口测试时如何处理接口或版本变更
  • 基于STM32的甲醛检测
  • Win10无法上网:Windows 无法访问指定设备、路径或文件。你可能没有适当的权限访问该项目找不到域 TEST 的域控制器DNS 解析存在问题
  • Git简介和发展
  • LeakCanary
  • 6. 存储池配置与CephFS创建 ceph version 14.2.22
  • Java 中的反射详解
  • 发行基础:本地化BUG导致审核失败
  • 【AlphaFold2】深入浅出,Feature Embedding|学习笔记
  • 瑞士联邦主席凯勒-祖特尔、联邦副主席帕姆兰会见何立峰
  • 综艺还有怎样的新可能?挖掘小众文化领域
  • 游戏论|暴君无道,吊民伐罪——《苏丹的游戏》中的政治
  • 韩德洙成为韩国执政党总统大选候选人
  • 2025年度上海市住房城乡建设管理委工程系列中级职称评审工作启动
  • 中日有关部门就日本水产品输华问进行第三次谈判,外交部回应