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

访问者模式(Visitor Pattern)

🧠 访问者模式(Visitor Pattern)

访问者模式是一种行为型设计模式,它允许你在不改变对象结构的情况下,增加新的操作。简单来说,访问者模式可以使得你在不修改类的情况下,向已有的类中添加新的操作逻辑。

访问者模式的核心思想是:将数据结构与操作分离,把操作封装到访问者中。可以使得新增的操作可以通过访问者去执行,而无需修改数据结构本身。


🎯 为什么需要访问者模式?

  1. 扩展性强:访问者模式可以很容易地扩展新的操作,而不需要修改现有的数据结构或类。
  2. 双重分离:将操作和数据结构分离,允许数据结构和操作分开变化,符合“开闭原则”,易于维护和拓展。
  3. 封装行为:通过访问者模式封装多种操作,并避免修改原始类,减少类的复杂度。

优缺点分析

优点缺点
增加新的操作时不需要修改原有对象结构,符合开闭原则增加新的数据结构类时需要修改所有访问者,不利于数据结构的扩展
使得代码更符合“单一职责原则”,因为每个访问者只关心一种操作如果数据结构变化频繁,修改访问者可能成为负担
易于扩展新的操作而不影响原有代码复杂的系统中,访问者可能会增多,导致难以维护

🧩 Python 示例:图形绘制应用

假设有一个图形库,包含多个不同的形状:圆形矩形,我们希望能够对这些图形进行多个操作,例如计算面积、计算周长等。使用访问者模式可以实现动态增加新的操作,而不需要修改已有的图形类。

🎯 1️⃣ 图形接口(Shape)

from abc import ABC, abstractmethodclass Shape(ABC):@abstractmethoddef accept(self, visitor):pass
  • Shape 是所有图形的抽象类,定义了 accept() 方法,接受一个访问者对象来执行特定的操作。

🎯 2️⃣ 具体图形类(Concrete Shapes)

class Circle(Shape):def __init__(self, radius):self.radius = radiusdef accept(self, visitor):visitor.visit_circle(self)class Rectangle(Shape):def __init__(self, width, height):self.width = widthself.height = heightdef accept(self, visitor):visitor.visit_rectangle(self)
  • CircleRectangle 类是具体的图形类,分别代表圆形和矩形。
  • 每个图形类都实现了 accept() 方法,接受一个访问者,并将自身传递给访问者进行操作。

🎯 3️⃣ 访问者接口(Visitor)

class Visitor(ABC):@abstractmethoddef visit_circle(self, circle: Circle):pass@abstractmethoddef visit_rectangle(self, rectangle: Rectangle):pass
  • Visitor 类是一个抽象类,定义了每个图形类的访问方法。例如,visit_circle() 用于访问 Circle 对象,visit_rectangle() 用于访问 Rectangle 对象。

🎯 4️⃣ 具体访问者(Concrete Visitor)

class AreaVisitor(Visitor):def visit_circle(self, circle: Circle):# 计算圆形面积print(f"Area of Circle: {3.14 * circle.radius ** 2}")def visit_rectangle(self, rectangle: Rectangle):# 计算矩形面积print(f"Area of Rectangle: {rectangle.width * rectangle.height}")class PerimeterVisitor(Visitor):def visit_circle(self, circle: Circle):# 计算圆形周长print(f"Perimeter of Circle: {2 * 3.14 * circle.radius}")def visit_rectangle(self, rectangle: Rectangle):# 计算矩形周长print(f"Perimeter of Rectangle: {2 * (rectangle.width + rectangle.height)}")
  • AreaVisitorPerimeterVisitor 是具体的访问者类,分别用于计算图形的面积和周长。
  • 它们实现了 Visitor 接口的 visit_circle()visit_rectangle() 方法。

🎯 5️⃣ 客户端代码(执行操作)

# 创建图形
circle = Circle(5)
rectangle = Rectangle(4, 6)# 创建访问者
area_visitor = AreaVisitor()
perimeter_visitor = PerimeterVisitor()# 执行操作
circle.accept(area_visitor)  # 计算圆形的面积
circle.accept(perimeter_visitor)  # 计算圆形的周长rectangle.accept(area_visitor)  # 计算矩形的面积
rectangle.accept(perimeter_visitor)  # 计算矩形的周长
  • 我们创建了 CircleRectangle 两个图形对象。
  • 我们还创建了两个访问者:AreaVisitorPerimeterVisitor,用于计算图形的面积和周长。
  • 通过 accept() 方法,图形对象将自己传递给访问者,访问者执行相应的操作。

输出结果

Area of Circle: 78.5
Perimeter of Circle: 31.400000000000002
Area of Rectangle: 24
Perimeter of Rectangle: 20
  • AreaVisitor 计算了圆形和矩形的面积。
  • PerimeterVisitor 计算了圆形和矩形的周长。

🧭 类图(Mermaid)

接受
接受
«interface»
Shape
+accept(visitor: Visitor)
Circle
+accept(visitor: Visitor)
Rectangle
+accept(visitor: Visitor)
«interface»
Visitor
+visit_circle(circle: Circle)
+visit_rectangle(rectangle: Rectangle)
AreaVisitor
+visit_circle(circle: Circle)
+visit_rectangle(rectangle: Rectangle)
PerimeterVisitor
+visit_circle(circle: Circle)
+visit_rectangle(rectangle: Rectangle)

🧭 流程图(Mermaid)

User Circle Rectangle AreaVisitor PerimeterVisitor accept(AreaVisitor) visit_circle(Circle) "Area of Circle: 78.5" accept(PerimeterVisitor) visit_circle(Circle) "Perimeter of Circle: 31.4" accept(AreaVisitor) visit_rectangle(Rectangle) "Area of Rectangle: 24" accept(PerimeterVisitor) visit_rectangle(Rectangle) "Perimeter of Rectangle: 20" User Circle Rectangle AreaVisitor PerimeterVisitor

🧠 应用场景总结

场景示例
计算、处理复杂对象例如计算复合图形的面积和周长
扩展现有类的功能在不改变原始类的情况下添加新的操作
对象结构不常变化,但操作可能变化比如一个系统中对象结构不变,但可能需要动态改变操作行为

总结口诀

访问者模式
✅ 将操作封装到独立的访问者类中,避免修改原有类结构,符合开闭原则。
✅ 适用于需要在一个不常变化的对象结构上,动态增加新操作的场景。


如果你对访问者模式有其他问题或想了解更多细节,欢迎继续提问!

相关文章:

  • 【Springboot知识】Springboot计划任务Schedule详解
  • Dify - Embedding Rerank
  • 第六章 流量特征分析-蚁剑流量分析(玄机靶场系列)
  • 基于YOLOv8与LSKNet的遥感图像旋转目标检测新框架 —LSKblock注意力机制在小目标检测中的性能优化与SOTA探索
  • TCP/IP, CAN,LIN,SOCKET
  • 学习黑客Nmap 实战
  • Python字符串全面指南:从基础到高级操作
  • 代码随想录算法训练营Day45
  • MCP原理详解及实战案例(动嘴出UI稿、3D建模)
  • GESP2024年3月认证C++八级( 第二部分判断题(6-10))
  • 用Python打造自己的专属命令行工具
  • AI融合SEO关键词优化
  • BC35 判断字母
  • 【AI论文】KeySync:一种在高分辨率下实现无泄漏唇形同步的稳健方法
  • 【day03】简写单词 | dd爱框框 | 除2!
  • WebAssembly(Wasm):现代Web开发的超级加速器
  • 网星安全AWS攻防方案,重磅发布!
  • PCI/PCIe Error?设备总线?Bus?
  • Jmeter性能测试工具使用介绍
  • item_get_app_pro - 获得淘宝app商品详情原数据操作流程
  • 牛市早报|“五一”假期预计跨区域人员流动量累计14.67亿人次
  • 山大齐鲁医院护士论文现“男性确诊子宫肌瘤”,院方称将核实
  • 马斯克的“星舰基地”成为新城镇,首任市长为SpaceX员工
  • 熬夜又不想伤肝?方法只有一个
  • 辽宁男篮被横扫这一晚,中国篮球的一个时代落幕了
  • 中央宣传部、全国总工会联合发布2025年“最美职工”先进事迹