📜  访问者方法 - Python设计模式

📅  最后修改于: 2022-05-13 01:54:35.062000             🧑  作者: Mango

访问者方法 - Python设计模式

访问者方法是一种行为设计模式,它允许我们将算法与其操作的对象结构分开。它可以帮助我们在不改变现有类层次结构的情况下动态地添加新特性。所有的行为模式都被证明是处理对象之间通信的最佳方法。同样,当我们必须对一组相似类型的对象执行操作时使用它。
访问者方法由两部分组成:

  • 名为Visit()的方法由访问者实现,并为数据结构的每个元素使用和调用。
  • 提供接受访问者的Accept()方法的可访问类

设计组件

  • 客户端:客户端类充当访问者设计模式的类的消费者。它可以访问数据结构对象,并可以指示它们接受访问者以供将来处理。
  • 访问者:一个抽象类,用于声明所有可访问类的访问操作。
  • 具体访问者:每个访问者将负责不同的操作。对于每种类型的访问者,必须实现在抽象访问者中声明的所有访问方法。
  • 访问:接受操作由此类声明。它还充当使访问者能够访问对象的入口点。
  • 具体的Visitable:这些类实现了Visitable类并定义了accept操作。访问者对象使用接受操作传递给该对象。

不使用访客方法的问题

想象一下,您正在处理GeeksforGeeks的软件管理,他们已经开始了某些课程,例如 DSA、SDE 和 STL,这些课程对于正在为基于产品的公司做准备的学生来说绝对有用。但是您将如何处理数据库中的课程、教师、学生、班级、ID 的所有数据?如果你用一种简单直接的方法来处理这种情况,你肯定只会弄得一团糟。

访客问题图

访客问题图

使用访客方法的解决方案

让我们看一下上述问题的解决方案。访问者方法建议在称为访问者类的单独类中添加新行为,而不是将其与已经存在的类混合。我们将原始对象作为参数传递给访问者的方法,以便该方法可以访问所有必要的信息。

Python3
""" The Courses hierarchy cannot be changed to add new
   functionality dynamically. Abstract Crop class for
 Concrete Courses_At_GFG classes: methods defined in this class
 will be inherited by all Concrete Courses_At_GFG classes."""
 
class Courses_At_GFG:
 
    def accept(self, visitor):
        visitor.visit(self)
 
    def teaching(self, visitor):
        print(self, "Taught by ", visitor)
 
    def studying(self, visitor):
        print(self, "studied by ", visitor)
 
 
    def __str__(self):
        return self.__class__.__name__
 
 
"""Concrete Courses_At_GFG class: Classes being visited."""
class SDE(Courses_At_GFG): pass
 
class STL(Courses_At_GFG): pass
 
class DSA(Courses_At_GFG): pass
 
 
""" Abstract Visitor class for Concrete Visitor classes:
 method defined in this class will be inherited by all
 Concrete Visitor classes."""
class Visitor:
 
    def __str__(self):
        return self.__class__.__name__
 
 
""" Concrete Visitors: Classes visiting Concrete Course objects.
 These classes have a visit() method which is called by the
 accept() method of the Concrete Course_At_GFG classes."""
class Instructor(Visitor):
    def visit(self, crop):
        crop.teaching(self)
 
 
class Student(Visitor):
    def visit(self, crop):
        crop.studying(self)
 
 
"""creating objects for concrete classes"""
sde = SDE()
stl = STL()
dsa = DSA()
 
"""Creating Visitors"""
instructor = Instructor()
student = Student()
 
"""Visitors visiting courses"""
sde.accept(instructor)
sde.accept(student)
 
stl.accept(instructor)
stl.accept(student)
 
dsa.accept(instructor)
dsa.accept(student)


输出

SDE Taught by  Instructor
SDE studied by  Student
STL Taught by  Instructor
STL studied by  Student
DSA Taught by  Instructor
DSA studied by  Student

UML 图

以下是访问者方法的 UML 图

UML 图访问者方法

UML 图访问者方法

好处

  • 开放/封闭原则:在类中引入新行为很容易,它可以与不同类的对象一起工作,而无需对这些类进行更改。
  • 单一职责原则:同一行为的多个版本可以操作到同一个类中。
  • 添加实体:访问者方法中添加实体很容易,因为我们只需在访问者类中进行更改,并且不会影响现有项目。
  • 更新逻辑:如果更新了操作逻辑,那么我们只需要在访问者实现中进行更改,而不是在所有项目类中进行。

缺点

  • 大量更新:每当从主要层次结构中添加或删除类时,我们都必须更新每个访问者
  • 难以扩展:如果访问者类太多,那么扩展类的整个接口就变得非常困难。
  • 缺乏访问权限:有时访问者可能无法访问他们应该使用的某些类的私有字段。

适用性

  • 递归结构:访问者方法非常适用于目录树或 XML 结构等递归结构。 Visitor 对象可以访问递归结构中的每个节点
  • 执行操作:当我们必须对像树这样的复杂对象的所有元素执行操作时,我们可以使用访问者方法。

进一步阅读——C++ 中的访问者方法