22种设计模式——访问者模式

1. 概述

访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。在这里插入图片描述
老惯例从问题引入,假如你的团队开发了一款地图APP,和百度一样等我们常用的APP一样,地图上有很多地点和信息,图像中的每个节点既能代表复杂实体 (例如一座城市), 也能代表更精细的对象 (例如工业区和旅游景点等)。在程序内部, 每个节点的类型都由其所属的类来表示, 每个特定的节点则是一个对象。

一段时间后, 你接到了实现将图像导出到 XML 文件中的任务。 这些工作最初看上去非常简单。 你计划为每个节点类添加导出函数, 然后递归执行图像中每个节点的导出函数。 解决方案简单且优雅: 使用多态机制可以让导出方法的调用代码不会和具体的节点类相耦合。
在这里插入图片描述
但是你的方案,架构师老大不给通过,理由是:他认为这些代码已经是产品了, 不想冒险对其进行修改, 因为修改可能会引入潜在的缺陷。

还有另一个原因, 那就是在此项任务完成后, 营销部门很有可能会要求程序提供导出其他类型文件的功能, 或者提出其他奇怪的要求。 这样你很可能会被迫再次修改这些重要但脆弱的类。

那该怎么做呢?使用访问者模式!!!说句实话,访问者模式没啥用,因为使用它的场景实在是比较少,著名的四人帮的书对它也是很快就略过了,但我们还是要了解一下的。

他怎么做的呢?看下面代码吧,我感觉我讲不明白哈哈。我在初学访问者模式的时候,一直有个疑问,我发现代理模式和访问者模式的使用场景很相似,所以我偶尔弄混(可能只有我这样)。

比如上面那个问题,解决方法我们也可以用代理模式啊,干嘛还要用访问者模式,然后我找了别人的博客和别的例子看了下,总结了一下,代理模式的目的是在原有功能的基础上增强功能,访问者模式是在原有功能基础上新增功能,两者不是同一个角度,OVER。

  • 总结:访问者模式可以在一个无法直接修改代码的类,在原有基础上新增功能或属性,但又不必修改代码,只需要新增访问类。访问者模式的一个很大作用就是能使得程序具有很好的可扩展性。

2. 特点

  • 优点

    1. 开闭原则。你可以引入在不同类对象上执行的新行为, 且无需对这些类做出修改。
    2. 单一职责原则。 可将同一行为的不同版本移到同一个类中。
    3. 访问者对象可以在与各种对象交互时收集一些有用的信息。 当你想要遍历一些复杂的对象结构 (例如对象树), 并在结构中的每个对象上应用访问者时, 这些信息可能会有所帮助。
  • 缺点

    1. 每次在元素层次结构中添加或移除一个类时, 你都要更新所有的访问者。
    2. 在访问者同某个元素进行交互时, 它们可能没有访问元素私有成员变量和方法的必要权限。
  • 使用场景

    1. 如果你需要对一个复杂对象结构 (例如对象树) 中的所有元素执行某些操作, 可使用访问者模式。

      访问者模式通过在访问者对象中为多个目标类提供相同操作的变体, 让你能在属于不同类的一组对象上执行同一操作。

    2. 可使用访问者模式来清理辅助行为的业务逻辑

      该模式会将所有非主要的行为抽取到一组访问者类中, 使得程序的主要类能更专注于主要的工作。

    3. 当某个行为仅在类层次结构中的一些类中有意义, 而在其他类中没有意义时, 可使用该模式。

      你可将该行为抽取到单独的访问者类中, 只需实现接收相关类的对象作为参数的访问者方法并将其他方法留空即可。


3. 实现

下面的实现会使用到一个例子:关于硬件的驱动软件升级是很常见的一件事情吧,假如现在我们就抽象出了一个驱动的接口,也就是下面的Hardware,里面定义了每个具体硬件的驱动方法run(),我们都知道版本升级这个事情,偶尔改动大偶尔改动小,其实可以把每次版本更新看成是一个新增的功能,那这个不就正好满足我们访问者模式的需求吗,看下面代码。

  • UML类图
    在这里插入图片描述

  • 角色说明

    1. 访问者接口:这个接口里面写了一系列对应具体被访问者的方法
    2. 具体访问者:会为不同的具体被访问者类实现相同行为的几个不同版本
    3. 被访问者:定义了被访问者类的基本逻辑,但这里也要有一个accept(Visitor visitor)方法用于接入访问者
    4. 具体被访问者:具体被访问者,实现了具体逻辑
  • Java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值