访问者模式

本文介绍了访问者模式,被誉为最复杂的设计模式之一。通过一个应聘者与面试平台的示例,阐述了访问者模式的工作原理,包括应聘者接受面试平台访问、面试平台访问应聘者资料的关键步骤。同时,讨论了该模式的优缺点,如职责分离、良好的扩展性,以及可能带来的问题,如违反迪米特原则和依赖倒置原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

题外话:这是要写的23种设计模式的最后一种,还没写完的时候,总想着赶紧写赶紧写,现在马上就要写完了,感觉时间过得好快啊,为了写这个系列花了三个月的时间,不过也将这块硬骨头啃下来了,值得记录一下。

访问者模式,被誉为最复杂的设计模式,一般都用不上,刚开始接触的时候,确实是无法理解为什么要这么设计(来回套娃),感觉是为了封装而封装。下面我们来看看这个访问者模式是怎么套娃的吧。


正文

 样例demo

import random

class Interviewee:
    def __init__(self, name) -> None:
        self.name = name
        self.academic_record  = random.randrange(0,100)      # 学业成绩
        self.technical_proficiency = random.randrange(0,100) # 技术熟练度


    def accept(self, visitor):
        pass


class Student(Interviewee):

    def accept(self, visitor):
        visitor.visit(self)

    def get_academic_record(self):
        return self.academic_record


class SocialMan(Interviewee):

    def accept(self, visitor):
        visitor.visit(self)

    def get_technical_proficiency(self):
        return self.technical_proficiency


class Visitor:
    def __init__(self) -> None:
        pass

    def visit(self, interviewee) -> None:
        pass

class OnCampusRecruitment(Visitor):

    def visit(self, interviewee) -> None:
        print("校招平台")
        if isinstance(interviewee, Student): 
            print("面试者{}是学生,他的学业成绩是:{}".format(interviewee.name,interviewee.get_academic_record()))
        elif isinstance(interviewee, SocialMan):
            print("{}先生,您的简历投错了,请移步社招平台".format(interviewee.name))
        else:
            print("您哪位?")

        
class SocialRecruitment(Visitor):

    def visit(self, interviewee) -> None:
        print("社招平台")
        if isinstance(interviewee, Student): 
            print("{}同学,您简历投错了,请移步校招平台".format(interviewee.name))
        elif isinstance(interviewee, SocialMan):
            print("面试者{}是社会人,他的技术熟练度是:{}%".format(interviewee.name,interviewee.get_technical_proficiency()))
        else:
            print("您哪位?")


class InterviewList:

    def __init__(self) -> None:
        self.interview_list = []

    def add_interview(self,interviewee):
        self.interview_list.append(interviewee)

    def display(self, visitor):
        for interviewee in self.interview_list:
            interviewee.accept(visitor)

i = InterviewList()
i.add_interview(SocialMan("李四"))
i.add_interview(Student("小明"))
i.add_interview(Student("小红"))
i.add_interview(Student("小芳"))
i.add_interview(SocialMan("王五"))
i.add_interview(Student("小兰"))
i.add_interview(SocialMan("张三"))

i.display(SocialRecruitment())
i.display(OnCampusRecruitment())

样例解析:

例子中我们有个应聘者基类,这个应聘者基类有两个子类,一个是学生,一个是社会人。每个应聘者都有属于自己的学业成绩技能熟练度。 

有个面试平台基类,这个面试平台基类也有两个子类,一个是校招平台,一个是社招平台。每个面试平台关注的点不一样。校招平台只关注学生的学业成绩社招平台关注社会人的技能熟练度

现在我们有个应聘者中心,专门收集应聘者资料的,并且将应聘者资料投放到不同的面试平台。

面试流程如下:

应聘者投递简历到应聘中心应聘中心将所有应聘者投放到指定面试平台应聘者接受面试平台访问(accept(self,visitor))并将自己的资料传给面试平台查看(visit(self))。面试平台收到应聘者资料后,根据自己的需求访问相应的属性,并作出反馈。

上述流程主要有两个关键点:

  1. 应聘者接受面试平台访问accept(self,visitor)
  2. 面试者接受应聘者资料visit(self)

 


总结

访问者模式的优点 :

  1. 切换访问者比较方便,每次只需要指定不同的访问者即可

访问者模式的缺点:

  1. 新增被访者比较麻烦,可能需要改变访问者设定的访问方式
  2. 修改被访者属性和方法,会对访问者产生影响,导致修改所有访问者方式

 下面贴一小段百度来的总结:访问者模式一篇就够了 - 简书

  • 访问者模式的优点。

    1. 各角色职责分离,符合单一职责原则
      通过UML类图和上面的示例可以看出来,Visitor、ConcreteVisitor、Element 、ObjectStructure,职责单一,各司其责。
    2. 具有优秀的扩展性
      如果需要增加新的访问者,增加实现类 ConcreteVisitor 就可以快速扩展。
    3. 使得数据结构和作用于结构上的操作解耦,使得操作集合可以独立变化
      员工属性(数据结构)和CEO、CTO访问者(数据操作)的解耦。
    4. 灵活性
  • 访问者模式的缺点。

    1. 具体元素对访问者公布细节,违反了迪米特原则
      CEO、CTO需要调用具体员工的方法。
    2. 具体元素变更时导致修改成本大
      变更员工属性时,多个访问者都要修改。
    3. 违反了依赖倒置原则,为了达到“区别对待”而依赖了具体类,没有以来抽象
      访问者 visit 方法中,依赖了具体员工的具体方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值