访问者模式是一种行为型设计模式,它允许你在不改变对象结构的情况下,增加新的操作。简单来说,访问者模式可以使得你在不修改类的情况下,向已有的类中添加新的操作逻辑。
访问者模式的核心思想是:将数据结构与操作分离,把操作封装到访问者中。可以使得新增的操作可以通过访问者去执行,而无需修改数据结构本身。
✅ 优点 | ❌ 缺点 |
---|---|
增加新的操作时不需要修改原有对象结构,符合开闭原则 | 增加新的数据结构类时需要修改所有访问者,不利于数据结构的扩展 |
使得代码更符合“单一职责原则”,因为每个访问者只关心一种操作 | 如果数据结构变化频繁,修改访问者可能成为负担 |
易于扩展新的操作而不影响原有代码 | 复杂的系统中,访问者可能会增多,导致难以维护 |
假设有一个图形库,包含多个不同的形状:圆形、矩形,我们希望能够对这些图形进行多个操作,例如计算面积、计算周长等。使用访问者模式可以实现动态增加新的操作,而不需要修改已有的图形类。
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def accept(self, visitor):
pass
Shape
是所有图形的抽象类,定义了 accept()
方法,接受一个访问者对象来执行特定的操作。class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def accept(self, visitor):
visitor.visit_circle(self)
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def accept(self, visitor):
visitor.visit_rectangle(self)
Circle
和 Rectangle
类是具体的图形类,分别代表圆形和矩形。accept()
方法,接受一个访问者,并将自身传递给访问者进行操作。class Visitor(ABC):
@abstractmethod
def visit_circle(self, circle: Circle):
pass
@abstractmethod
def visit_rectangle(self, rectangle: Rectangle):
pass
Visitor
类是一个抽象类,定义了每个图形类的访问方法。例如,visit_circle()
用于访问 Circle
对象,visit_rectangle()
用于访问 Rectangle
对象。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)}")
AreaVisitor
和 PerimeterVisitor
是具体的访问者类,分别用于计算图形的面积和周长。Visitor
接口的 visit_circle()
和 visit_rectangle()
方法。# 创建图形
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) # 计算矩形的周长
Circle
和 Rectangle
两个图形对象。AreaVisitor
和 PerimeterVisitor
,用于计算图形的面积和周长。accept()
方法,图形对象将自己传递给访问者,访问者执行相应的操作。Area of Circle: 78.5
Perimeter of Circle: 31.400000000000002
Area of Rectangle: 24
Perimeter of Rectangle: 20
AreaVisitor
计算了圆形和矩形的面积。PerimeterVisitor
计算了圆形和矩形的周长。场景 | 示例 |
---|---|
计算、处理复杂对象 | 例如计算复合图形的面积和周长 |
扩展现有类的功能 | 在不改变原始类的情况下添加新的操作 |
对象结构不常变化,但操作可能变化 | 比如一个系统中对象结构不变,但可能需要动态改变操作行为 |
访问者模式:
✅ 将操作封装到独立的访问者类中,避免修改原有类结构,符合开闭原则。
✅ 适用于需要在一个不常变化的对象结构上,动态增加新操作的场景。
如果你对访问者模式有其他问题或想了解更多细节,欢迎继续提问!