Python使用方法重载实现访问者模式

 更新时间:2024年12月17日 10:23:28   作者:三叔木卯  
这篇文章主要为大家详细介绍了Python如何使用方法重载实现访问者模式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

Python上的访问者模式,看了一下网上其他人的例子,一般都是类似下面的代码。

from abc import ABC, abstractmethod  
  
# 抽象访问者  
class AnimalVisitor(ABC):  
    @abstractmethod  
    def visit_dog(self, dog: "Dog"):  
        pass  
  
    @abstractmethod  
    def visit_cat(self, cat: "Cat"):  
        pass  
  
# 抽象动物类  
class Animal(ABC):  
    def __init__(self, name: str):  
        self.name = name  
  
    @abstractmethod  
    def accept(self, visitor: AnimalVisitor):  
        pass  
  
# 具体动物类  
class Dog(Animal):  
    def accept(self, visitor):  
        visitor.visit_dog(self)  
  
class Cat(Animal):  
    def accept(self, visitor):  
        visitor.visit_cat(self)  
  
# 具体访问者:喂食访问者  
class FeedingVisitor(AnimalVisitor):  
    def visit_dog(self, dog):  
        print(f"给{dog.name}喂狗粮")  
  
    def visit_cat(self, cat):  
        print(f"给{cat.name}喂猫粮")  
  
# 具体访问者:检查健康访问者  
class HealthCheckVisitor(AnimalVisitor):  
    def visit_dog(self, dog):  
        print(f"检查{dog.name}的疫苗接种情况")  
  
    def visit_cat(self, cat):  
        print(f"检查{cat.name}是否需要洗澡")

使用示例如下:

def main():  
    # 创建动物  
    dog = Dog("旺财")  
    cat = Cat("咪咪")  
  
    # 创建访问者  
    feeding_visitor = FeedingVisitor()  
    health_visitor = HealthCheckVisitor()  
  
    # 创建动物列表  
    animals = [dog, cat]  
  
    # 执行不同的操作  
    print("=== 喂食时间 ===")  
    for animal in animals:  
        animal.accept(feeding_visitor)  
  
    print("\n=== 健康检查 ===")  
    for animal in animals:  
        animal.accept(health_visitor)
  
  
if __name__ == "__main__":  
    main()

以上实现的访问者模式,访问者的接口类(抽象类)一般通过定义不同的方法(带visit前缀的方法)来对不同的被访问者进行访问。有些奇怪,为什么不通过方法重载的方式来实现访问者模式呢?

通过定义不同方法来实现访问者模式,明显违背一些设计原则的。访问者的接口类需要负责访问不同方法,而这些方法之间相关性不大(删除某个方法对其他方法没有影响),这明显违背了单一职责原则(SRP);如果要添加一种动物(被访问者),那么就要修改访问者接口类以添加相应的方法,这是违背开闭原则(OCP)的;访问者的接口类的方法还依赖了具体类(比如DogCat类),这违背了依赖倒转原则(DIP)

使用方法重载实现的访问者模式,则没有上面的问题,而且代码也更简单明了。Python没有传统的方法重载方式,不过在functools模块里有个singledispatchmethod单分派装饰器,这里可以借用它来实现“方法重载”。

使用方法重载的方式代码如下:

from abc import ABC, abstractmethod  
from functools import singledispatchmethod  
  
# 抽象访问者  
class AnimalVisitor(ABC):  
    @abstractmethod  
    def visit(self, animal: "Animal"):  
        pass  
  
# 抽象动物类  
class Animal(ABC):  
    def __init__(self, name: str):  
        self.name = name  
  
    def accept(self, visitor: AnimalVisitor):  
        visitor.visit(self)  
  
# 具体动物类  
class Dog(Animal): ...  
  
class Cat(Animal): ...  
  
# 具体访问者:喂食访问者  
class FeedingVisitor(AnimalVisitor):  
    @singledispatchmethod  
    def visit(self, animal: Animal):  
        raise NotImplementedError(f"{type(animal)} 未重载 visit方法")  
  
    @visit.register(Dog)  
    def _(self, dog):  
        print(f"给{dog.name}喂狗粮")  
  
    @visit.register(Cat)  
    def _(self, cat):  
        print(f"给{cat.name}喂猫粮")  
  
# 具体访问者:检查健康访问者  
class HealthCheckVisitor(AnimalVisitor):  
  
    @singledispatchmethod  
    def visit(self, animal: Animal):  
        raise NotImplementedError(f"{type(animal)} 未重载 visit方法")  
  
    @visit.register(Dog)  
    def _(self, dog):  
        print(f"检查{dog.name}的疫苗接种情况")  
  
    @visit.register(Cat)  
    def _(self, cat):  
        print(f"检查{cat.name}是否需要洗澡")

可以看到,这一种方式访问者抽象类AnimalVisitor的方法只有一个,就是visitAnimalVisitor只负责一个职责,那就是访问动物,符合单一职责原则;添加其他种动物的时候,不用修改抽象类,符合开闭原则AnimalVisitor现在只依赖Animal这个抽象类,符合依赖倒转原则

有人可能担心,如果访问者抽象类没有把访问动物类的相应方法都列出来,会导致具体访问者类漏实现一些方法重载。这个问题在上面的代码中考虑到了,在singledispatchmethod装饰的visit方法里使用NotImplementedError异常进行防御,如果某个具体动物类没有重载visit方法,将抛出异常。

到此这篇关于Python使用方法重载实现访问者模式的文章就介绍到这了,更多相关Python访问者模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python爬虫学习笔记之Beautifulsoup模块用法详解

    python爬虫学习笔记之Beautifulsoup模块用法详解

    这篇文章主要介绍了python爬虫学习笔记之Beautifulsoup模块用法,结合实例形式详细分析了python爬虫Beautifulsoup模块基本功能、原理、用法及操作注意事项,需要的朋友可以参考下
    2020-04-04
  • 如何编写python的daemon程序

    如何编写python的daemon程序

    这篇文章主要介绍了如何编写python的daemon程序,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下
    2021-01-01
  • django-rest-framework 自定义swagger过程详解

    django-rest-framework 自定义swagger过程详解

    这篇文章主要介绍了django-rest-framework 自定义swagger过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Python datetime 如何处理时区信息

    Python datetime 如何处理时区信息

    这篇文章主要介绍了Python datetime 如何处理时区信息,帮助大家更好的用python 处理时间,感兴趣的朋友可以了解下。
    2020-09-09
  • Python爬虫天气预报实例详解(小白入门)

    Python爬虫天气预报实例详解(小白入门)

    这篇文章主要介绍了Python爬虫天气预报实例详解(小白入门),详细介绍了整个爬虫建立的流程,最后分享了实现代码,很简洁,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 使用IronPython把Python脚本集成到.NET程序中的教程

    使用IronPython把Python脚本集成到.NET程序中的教程

    这篇文章主要介绍了使用IronPython把Python脚本集成到.NET程序中的教程,现在刚刚被微软开源的.NET重新成为业界热点、本文介绍了使Python和.NET交互的IronPython,需要的朋友可以参考下
    2015-03-03
  • python迭代器的使用方法实例

    python迭代器的使用方法实例

    这篇文章主要介绍了python迭代器的使用方法,代码很简单,大家可以参考使用
    2013-11-11
  • python文件编写好后如何实践

    python文件编写好后如何实践

    在本篇文章里小编给大家分享了关于python文件编写好后如何实践的相关内容,需要的朋友们可以参考下。
    2020-07-07
  • 使用PyTorch实现手写数字识别功能

    使用PyTorch实现手写数字识别功能

    在人工智能的世界里,计算机视觉是最具魅力的领域之一,通过PyTorch这一强大的深度学习框架,我们将在经典的MNIST数据集上,见证一个神经网络从零开始学会识别数字的全过程,本文给大家介绍了如何使用PyTorch实现手写数字识别,需要的朋友可以参考下
    2025-03-03
  • 使用 Python 合并多个格式一致的 Excel 文件(推荐)

    使用 Python 合并多个格式一致的 Excel 文件(推荐)

    这篇文章主要介绍了使用 Python 合并多个格式一致的 Excel 文件,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12

最新评论