python: Visitor Pattern

访问者模式的核心是将数据结构与数据操作分离,允许你在不修改原有数据结构(珠宝类)的前提下,为其增加新的操作(比如估值、鉴定、清洁)。下面我会用珠宝(钻石、黄金、翡翠)作为核心数据结构,用不同的访问者(估值师、鉴定师、清洁师)作为操作,完整实现并解释这个模式。

python 复制代码
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:40
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : Jewelry.py
 
from abc import ABC, abstractmethod
 
# ====================== 1. 定义元素(珠宝)接口 ======================
class Jewelry(ABC):
    """
    珠宝抽象类(元素接口),定义接受访问者的方法
    """
    @abstractmethod
    def accept(self, visitor):
        """
        接受访问者访问的核心方法
        :param visitor:
        :return:
        """
        pass
python 复制代码
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:41
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : Diamond.py
 
from VisitorPattern.Jewelry import Jewelry
 
 
# ====================== 2. 具体元素(各类珠宝) ======================
class Diamond(Jewelry):
    """
    钻石(具体元素)
    """
    def __init__(self, carat: float, clarity: str):
        """
 
        :param carat:
        :param clarity:
        """
 
        self.carat = carat  # 克拉
        self.clarity = clarity  # 净度(VS1、VVS1等)
 
    def accept(self, visitor):
        """
        调用访问者的「访问钻石」方法,并传入自身
        :param visitor:
        :return:
        """
        visitor.visit_diamond(self)
 
 
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:42
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : Gold.py
 
from VisitorPattern.Jewelry import Jewelry
 
 
# ====================== 2. 具体元素(各类珠宝) ======================
 
class Gold(Jewelry):
    """
    黄金(具体元素)
    """
    def __init__(self, weight: float, purity: float):
        """
         
        :param weight:
        :param purity:
        """
        self.weight = weight  # 克重
        self.purity = purity  # 纯度(如999、9999)
 
    def accept(self, visitor):
        """
         
        :param visitor:
        :return:
        """
        visitor.visit_gold(self)
 
 
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:43
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : Jade.py
 
 
from VisitorPattern.Jewelry import Jewelry
 
 
# ====================== 2. 具体元素(各类珠宝) ======================
 
class Jade(Jewelry):
    """
    翡翠(具体元素)
    """
    def __init__(self, grade: str, size: float):
        """
 
        :param grade:
        :param size:
        """
        self.grade = grade  # 品级(A、B、C)
        self.size = size  # 尺寸(cm³)
 
    def accept(self, visitor):
        """
 
        :param visitor:
        :return:
        """
        visitor.visit_jade(self)
python 复制代码
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:45
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : JewelryVisitor.py
from VisitorPattern.Gold import Gold
from VisitorPattern.Jade import Jade
from VisitorPattern.Diamond import Diamond
from abc import ABC, abstractmethod
 
 
# ====================== 3. 定义访问者接口 ======================
class JewelryVisitor(ABC):
    """
    珠宝访问者抽象接口,定义对所有珠宝的访问方法
    """
    @abstractmethod
    def visit_diamond(self, diamond: Diamond):
        """
 
        :param diamond:
        :return:
        """
        pass
 
    @abstractmethod
    def visit_gold(self, gold: Gold):
        """
 
        :param gold:
        :return:
        """
        pass
 
    @abstractmethod
    def visit_jade(self, jade: Jade):
        """
 
        :param jade:
        :return:
        """
        pass
python 复制代码
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:48
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : ValuationVisitor.py
 
from VisitorPattern.Gold import Gold
from VisitorPattern.Jade import Jade
from VisitorPattern.Diamond import Diamond
from VisitorPattern.JewelryVisitor import JewelryVisitor
 
 
 
# ====================== 4. 具体访问者(不同操作) ======================
class ValuationVisitor(JewelryVisitor):
    """
    估值访问者:为不同珠宝计算价值
    """
    def __init__(self):
        """
 
        """
        self.total_value = 0  # 总估值
 
    def visit_diamond(self, diamond: Diamond):
        """
        钻石估值:克拉 * 净度系数(VVS1=10000, VS1=8000)
        :param diamond:
        :return:
        """
 
        clarity_coeff = 10000 if diamond.clarity == "VVS1" else 8000
        value = diamond.carat * clarity_coeff
        self.total_value += value
        print(f"钻石({diamond.carat}克拉,{diamond.clarity})估值:{value} 元")
 
    def visit_gold(self, gold: Gold):
        """
        黄金估值:克重 * 纯度系数 * 基础金价(假设基础金价400元/克)
        :param gold:
        :return:
        """
 
        purity_coeff = gold.purity / 999  # 999纯金系数为1
        value = gold.weight * purity_coeff * 400
        self.total_value += value
        print(f"黄金({gold.weight}克,{gold.purity}纯)估值:{value:.2f} 元")
 
    def visit_jade(self, jade: Jade):
        """
        翡翠估值:尺寸 * 品级系数(A=5000, B=1000, C=100)
        :param jade:
        :return:
        """
        grade_coeff = {"A": 5000, "B": 1000, "C": 100}[jade.grade]
        value = jade.size * grade_coeff
        self.total_value += value
        print(f"翡翠({jade.size}cm³,{jade.grade}级)估值:{value} 元")
 
 
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:50
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : AppraisalVisitor.py
from VisitorPattern.Gold import Gold
from VisitorPattern.Jade import Jade
from VisitorPattern.Diamond import Diamond
from VisitorPattern.JewelryVisitor import JewelryVisitor
 
 
# ====================== 4. 具体访问者(不同操作) ======================
 
 
class AppraisalVisitor(JewelryVisitor):
    """
    鉴定访问者:鉴定珠宝真伪/品质
    """
    def visit_diamond(self, diamond: Diamond):
        """
 
        :param diamond:
        :return:
        """
        result = "真品" if diamond.clarity in ["VVS1", "VS1"] else "仿品"
        print(f"钻石鉴定结果:{result}(净度{diamond.clarity})")
 
    def visit_gold(self, gold: Gold):
        """
 
        :param gold:
        :return:
        """
        result = "足金" if gold.purity >= 999 else "非足金"
        print(f"黄金鉴定结果:{result}(纯度{gold.purity})")
 
    def visit_jade(self, jade: Jade):
        """
 
        :param jade:
        :return:
        """
 
        result = "天然翡翠" if jade.grade == "A" else "处理翡翠"
        print(f"翡翠鉴定结果:{result}(品级{jade.grade})")
 
 
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:51
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : CleaningVisitor.py
from VisitorPattern.Gold import Gold
from VisitorPattern.Jade import Jade
from VisitorPattern.Diamond import Diamond
from VisitorPattern.JewelryVisitor import JewelryVisitor
 
 
 
# ====================== 4. 具体访问者(不同操作) ======================
 
class CleaningVisitor(JewelryVisitor):
    """
    清洁访问者:根据珠宝类型执行不同清洁方式
    """
    def visit_diamond(self, diamond: Diamond):
        """
 
        :param diamond:
        :return:
        """
 
        print(f"钻石清洁:使用超声波清洗(适配{diamond.clarity}净度)")
 
    def visit_gold(self, gold: Gold):
        """
 
        :param gold:
        :return:
        """
 
        print(f"黄金清洁:使用高温蒸汽清洗(适配{gold.purity}纯度)")
 
    def visit_jade(self, jade: Jade):
        """
 
        :param jade:
        :return:
        """
        print(f"翡翠清洁:使用软布擦拭(适配{jade.grade}品级)")
python 复制代码
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:53
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : JewelryCollection.py
 
from VisitorPattern.Jewelry import Jewelry
from VisitorPattern.JewelryVisitor import JewelryVisitor
 
 
 
# ====================== 5. 对象结构(珠宝集合) ======================
class JewelryCollection(object):
    """
    珠宝集合:管理所有珠宝,提供遍历访问的方法
    """
    def __init__(self):
        """
 
        """
        self.jewelry_items = []
 
    def add_jewelry(self, jewelry: Jewelry):
        """
 
        :param jewelry:
        :return:
        """
        self.jewelry_items.append(jewelry)
 
    def accept(self, visitor: JewelryVisitor):
        """
        遍历所有珠宝,让访问者访问每一个
        :param visitor:
        :return:
        """
 
 
        for item in self.jewelry_items:
            item.accept(visitor)
python 复制代码
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:访问者模式(Visitor Pattern)
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/2/23 17:55
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : VisitorBll.py
from VisitorPattern.Gold import Gold
from VisitorPattern.Jade import Jade
from VisitorPattern.Diamond import Diamond
 
from VisitorPattern.CleaningVisitor import CleaningVisitor
from VisitorPattern.ValuationVisitor import ValuationVisitor
from VisitorPattern.AppraisalVisitor import AppraisalVisitor
from VisitorPattern.JewelryCollection import JewelryCollection
 
 
class VisitorBll(object):
    """
    示例
    """
    def demo(self):
        """
 
        :return:
        """
        # 1. 创建珠宝集合并添加珠宝
        collection = JewelryCollection()
        collection.add_jewelry(Diamond(1.2, "VVS1"))  # 1.2克拉VVS1钻石
        collection.add_jewelry(Gold(20.5, 999))  # 20.5克999纯金
        collection.add_jewelry(Jade("A", 5.0))  # 5cm³A级翡翠
 
        print("=" * 50 + "\n1. 珠宝估值")
        valuer = ValuationVisitor()
        collection.accept(valuer)
        print(f"所有珠宝总估值:{valuer.total_value:.2f} 元")
 
        print("=" * 50 + "\n2. 珠宝鉴定")
        appraiser = AppraisalVisitor()
        collection.accept(appraiser)
 
        print("=" * 50 + "\n3. 珠宝清洁")
        cleaner = CleaningVisitor()
        collection.accept(cleaner)

调用:

python 复制代码
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2026/2/18 20:58
# User      : geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : main.py
# explain   : 学习
from bll.MementoBll import MementoBll
from bll.CommandBll import CommandBll
from bll.StateBll import StateBll
from bll.TemplateMethodBll import TemplateMethodBll
from bll.VisitorBll import VisitorBll
 
if __name__ == '__main__':
 
    #实现备忘录模式(Memento Pattern)
    #mementobll= MementoBll()
    #mementobll.demo()
    #命令模式(Command Pattern)
    #commandBll= CommandBll()
    #commandBll.demo()
    # 状态模式 State Pattern
    #stateBll =StateBll()
    #stateBll.demo()
    # 模板方法模式 Template Method Pattern
    #templateMethodBll= TemplateMethodBll()
    #templateMethodBll.demo()
    # 访问者模式(Visitor Pattern)
    visitor = VisitorBll()
    visitor.demo()
 
 
    print('hi,welcome geovindu.')

输出:

相关推荐
五阿哥永琪2 小时前
常见设计模式简介
设计模式
哈里谢顿2 小时前
TCP 线程池连接耗尽故障排查指导
python
zhaoyin19943 小时前
关于文件读取中使用的斜杠问题
python
勇往直前plus4 小时前
从文件到屏幕:Python/java 字符编码、解码、文本处理的底层逻辑解析
java·开发语言·python
~央千澈~4 小时前
优雅草科技2026年2月重磅产品·优雅草·写作中枢 — 产品介绍与发布说明
python
Emotional。8 小时前
2025 年度技术总结与规划:AI 时代的开发者成长之路
人工智能·python·ai·langchain
资深web全栈开发11 小时前
CQS - 命令查询分离:驯服副作用
设计模式
witAI11 小时前
**AI仿真人剧制作软件2025推荐,解锁沉浸式数字内容创作
人工智能·python
Codefengfeng12 小时前
Python Base环境中加包的方法
开发语言·python