访问者模式对于动态类型语言有用吗?

2024-03-30

访问者模式允许在不扩展对象类的情况下编写对对象的操作。当然。但为什么不直接编写一个全局函数或静态类来从外部操作我的对象集合呢?基本上,在像 java 这样的语言中,accept()出于技术原因需要方法;但在一种语言中我可以实现相同的设计而无需accept()方法,访问者模式变得微不足道了吗?

说明:在Visitor模式中,可访问的类(实体)有一个方法.accept()他的工作是给访客打电话.visit()方法靠自己。我可以看到java示例的逻辑:访问者定义了不同的.visit(n)每种可访问类型的方法n它支持,并且.accept()必须使用技巧在运行时在它们之间进行选择。但是像 python 或 php 这样的语言具有动态类型并且没有方法重载。如果我是访问者,我可以调用实体方法(例如,.serialize())而不知道实体的类型,甚至不知道方法的完整签名。 (这就是“双重调度”问题,对吧?)

我知道接受方法可以将受保护的数据传递给访问者,但这有什么意义呢?如果数据暴露给访问者类,那么它实际上是类接口的一部分,因为它的详细信息在类之外很重要。无论如何,暴露私人数据从来没有让我觉得这是访问者模式的重点。

所以看来在 python、ruby 或 php 中,我可以实现一个类似访问者的类,而无需在访问的对象中使用接受方法(并且无需反射),对吧?如果我可以使用一系列异构对象并调用它们的公共方法,而无需与“访问”类进行任何合作,那么这是否仍然值得称为“访问者模式”?我是否缺少该模式的本质,或者它只是归结为“编写一个从外部操纵对象以执行操作的新类”?

附言。我已经看过很多关于 SO 和其他地方的讨论,但找不到任何解决问题的内容this问题。欢迎指点。


访问者特别有用的地方是访问者需要打开访问者类型,并且无论出于何种原因,您都不希望将该知识编码到访问者中(考虑插件架构)。考虑以下 Python 代码:

访客风采

class Banana(object):
      def visit(self, visitor):
          visitor.process_banana(self) 

class Apple(object):
      def visit(self, visitor):
          visitor.process_apple(self) 

class VisitorExample(object):
      def process_banana(self, banana):
          print "Mashing banana: ", banana

      def process_banana(self, apple):
          print "Crunching apple: ", apple

(请注意,我们可以使用基类/混合来压缩访问者逻辑)。

与之比较:

非访客风格

class NonVisitorVisitor(object):
      def process(self, fruit):
          verb = {Banana: "Mashing banana: ", 
                  Apple: "Crunching apple: "}[type(fruit)]
          print verb, fruit

在第二个示例中,水果不需要“访问者”的任何特殊支持,并且“访问者”处理给定类型的逻辑缺失。

相比之下,在 Java 或 C++ 中,第二个示例实际上是不可能的,并且访问方法(在访问者中)可以使用一个名称来引用过程方法的所有版本;编译器将选择适用于正在传递的类型的版本;并且访问者可以轻松地为访问者类型的根类提供默认实现。访问者中还需要有一个访问方法,因为方法变体(例如process(Banana b) vs process(Apple a)) 在编译时为访问者生成的代码中选择visit method.

因此,在像 Python 或 Ruby 这样的语言中,没有参数类型的分派(或者更确切地说,程序员必须自己实现它),因此不需要访问者模式。或者,有人可能会说,如果不通过访问者方法进行调度,访问者模式可以更好地实现。

一般来说,在Python、Ruby或Smalltalk等动态语言中,最好让“visitee”类携带所需的所有信息(这里是动词applicable),并在必要时提供钩子来支持“visitor”,例如作为命令或策略模式,或使用此处显示的非访问者模式。

结论

非访问者是实现类型切换逻辑的一种干净方式,尽管显式类型切换通常是一种代码味道。请记住,Java 和 C++ 的实现方式也是在 Visitor 中显式切换;这些语言中模式的优雅之处在于,它避免了访问者中具有显式的切换逻辑,而这在具有无类型变量的动态语言中是不可能的。因此,顶部的访问者模式对于动态语言来说是不利的,因为它再现了静态语言中访问者模式试图避免的错误。

使用模式的问题在于,您必须了解它们想要实现的目标,以及它们如何通过具体考虑的语言机制来实现这些目标,而不是盲目地复制 UML 图。在这种情况下,实现相同优点的模式看起来不同,并且具有不同的调用模式。这样做不仅可以使它们适应不同的语言,而且还可以适应同一语言中的不同具体情况。

更新:这是一篇关于实现此模式的 ruby​​ 文章:http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html

对我来说,双重调度似乎相当被迫;据我所知,你可以直接取消它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

访问者模式对于动态类型语言有用吗? 的相关文章

  • 如何用pygame画一条虚线?

    我需要在坐标系上绘制正弦波和余弦波 就像在this https i stack imgur com DGI8g png图片 除了没能代表以外 我所有的工作都做得很好虚线和曲线与 pygame 一致 我有与我需要的类似的东西 但我怎样才能让它
  • Elasticquent(ElasticSearch) Laravel 限制

    您好 我尝试使用 elasticSearch 查询获取所有结果 但如果 limit 值为 null 则仅返回 10 个结果 videos Video searchByQuery match gt field gt request gt fi
  • PHP strtotime +1 个月添加额外一个月[重复]

    这个问题在这里已经有答案了 我有一个简单的变量 可以将今天添加一个月 endOfCycle date Y m strtotime 1 month 今天是 2013 年 1 月 所以我希望返回 2013 02 但我得到的是 2013 03 我
  • pandas DataFrame 中行的高效成对比较

    我目前正在处理一个较小的数据集 大约 900 万行 不幸的是 大多数条目都是字符串 即使强制类别 框架在内存中也只有几 GB 我想做的是将每一行与其他行进行比较 并对内容进行直接比较 例如 给定 A B C D 0 cat blue old
  • Python:处理图像并保存到文件流

    我需要使用 python 处理图像 应用过滤器和其他转换 然后使用 HTTP 将其提供给用户 现在 我正在使用 BaseHTTPServer 和 PIL 问题是 PIL 无法直接写入文件流 因此我必须写入临时文件 然后读取该文件 以便将其发
  • Python 模块 BeautifulSoup 提取锚点 href

    我正在使用 BeautifulSoup 模块通过以下方式从 html 选择所有 href def extract links html soup BeautifulSoup html anchors soup findAll a print
  • 使用最新值进行采样

    考虑以下系列 created at 2014 01 27 21 50 05 040961 80000 00 2014 03 12 18 46 45 517968 79900 00 2014 09 05 20 54 17 991260 636
  • 如何在 tkinter 后台运行函数[重复]

    这个问题在这里已经有答案了 我是 GUI 编程新手 我想用 tkinter 编写一个 Python 程序 我想要它做的就是在后台运行一个可以通过 GUI 影响的简单函数 该函数从 0 计数到无穷大 直到按下按钮为止 至少这是我想要它做的 但
  • 我可以在类变量中添加没有指定值的 PHP 数组键吗?

    我目前正在努力通过IBM 关于 CakePHP 的教程 http www 128 ibm com developerworks edu os dw os php cake1 html 有一次我遇到了这段代码
  • 类型错误:无法连接“str”和“int”对象有人可以帮助新手使用他们的代码吗?

    感谢任何帮助 还有任何重大缺陷或您在格式或基本方面看到的任何重大缺陷 请指出 谢谢 day raw input How many days locations raw input Where to days str day location
  • 在 Keras 中使用有状态 LSTM 训练多变量多级数回归问题

    我有时间序列P过程 每个过程的长度各不相同 但都有 5 个变量 维度 我试图预测测试过程的估计寿命 我正在用有状态的方法来解决这个问题LSTM在喀拉斯 但我不确定我的训练过程是否正确 我将每个序列分成长度的批次30 所以每个序列都是这样的形
  • numpy 向量化而不是 for 循环

    我用 Python 写了一些代码 运行良好 但速度很慢 我认为是由于 for 循环 我希望可以使用 numpy 命令加速以下操作 让我定义目标 假设我有一个 2D numpy 数组all CMs尺寸row x col 例如考虑一个6x11数
  • Symfony错误在链配置的命名空间XXX中找不到类XXX

    关于这个主题已经有一些其他问题 但没有一个真正有帮助 我是 Symfony 的新手 所以很难理解它 我在文件 Client IntranetBundle LDAP LDAPAuthenticationProvider php 中 此代码导致
  • 根据标签位置计算 Pandas DataFrame 的索引

    我正在尝试计算标签的索引Pandas https pandas pydata org DataFrame在每一列中 基本上我有以下内容DataFrame d col1 label1 label2 label3 col2 label2 lab
  • 有没有办法重置特定类的所有静态属性?

    您可能知道 静态属性使测试变得困难 有没有办法将特定类的所有静态属性重置回其初始状态 理想情况下 这不需要为每个类定制代码 但可以通过继承以通用方式使用 或者完全从类外部使用 请不要回复 不要使用静态属性 之类的内容 谢谢 假设您正在使用
  • 正则表达式:如果字符串包含空格则不匹配

    仅当字符串不包含空格时 我似乎无法找出匹配字符串的正则表达式模式 例如 this has whitespace match some pattern 应该返回nil but nowhitespace match some pattern 应
  • Yii框架异步请求

    我有一个执行 3 个任务的 ajax 请求 保存模型 数据库 发电子邮件 给出成功或失败的消息 因为这个任务需要的时间太长了 用户最多可以等待 20 秒以获得响应 成功或失败消息 如果用户关闭浏览器 则其会停止用户当前进程的操作之一 这是糟
  • Python 子进程:无法转义引号

    我知道以前曾问过类似的问题 但它们似乎都是通过重新设计参数的传递方式 即使用列表等 来解决的 但是 我这里有一个问题 因为我没有这个选项 有一个特定的命令行程序 我使用的是 Bash shell 我必须向其传递带引号的字符串 它不能不被引用
  • 如何将 JSON 文本转换为 PHP 关联数组

    我将以下 JSON 对象存储在文本文件 data txt 中 player black time 0 from 2c to 3d 我使用 php 阅读 问题 有没有简单的方法可以转换 data到 PHP 关联数组 我尝试过使用json de
  • python:日志记录:我们可以向记录器添加多个过滤器吗?考虑哪一个

    我试图了解 Python 日志记录中的多个过滤器 一个在配置中定义 另一个在代码中定义 如何工作 我正在开发一个 Django 项目 下面是我在 settings py 中的记录器配置 我的目标是switch on and switch o

随机推荐

  • inputParser 验证参数未按预期运行

    我编写了一个测试函数 但遇到了麻烦inputParser function doit varargin p inputParser p KeepUnmatched 1 why does this bomb if I put in ischa
  • 从客户端 javascript/jquery 访问 Windows Azure 队列

    对于 UI 功能 我需要从 Windows Azure 队列中读取数据并相应地更新 UI 我看到很多 node js 示例 但没有看到使用纯 Javascript 或 Jquery 的示例 天蓝色查询 http azurequery cod
  • ui-bootstrap 模态范围错误

    我注意到 ui bootstrap 模态范围有一些奇怪的地方 似乎在其中使用 ng model 时 您必须引用 parent 才能到达模态控制器的范围 请注意 在我的 plunker 中 其他属性 例如 ng options 不需要 par
  • 如何在电子邮件主题中添加链接(gmail)

    有没有办法在电子邮件主题中添加链接 以下是 YouTube 的示例 在我的代码中 我正在尝试以下但结果仍然不令人满意 下面的代码发送主题 因为它打印了主题中的整个锚标记 public function contact us data fro
  • 如何以编程方式将 Google Sheet 脚本发布/部署为 API 可执行文件? [复制]

    这个问题在这里已经有答案了 我有一个包含脚本的谷歌工作表 我想以编程方式执行以下操作 制作这个 Google 电子表格public以编程方式 我想以编程方式为任何用户 公众 执行与上述电子表格关联的脚本 我可以表演 Publish gt D
  • Google Play 开发者 API - “当前用户没有足够的权限来执行请求的操作。”

    我有一个 Google 开发控制台进程 启用了 Google Play Developer API 并且该项目链接到 Google Play 项目 在 Google Dev 控制台项目中 创建了 OAuth 客户端 ID Web 应用程序
  • 如何指示Lucene中的StandardAnalyzer不删除停用词?

    简单问题 如何制作Lucene的StandardAnalyzer在分析我的句子时不要删除停用词 答案取决于版本 为了Lucene 3 0 3 当前 http lucene apache org java 3 0 3 api core org
  • 如何添加链接到 Flash 横幅

    我主要是一名开发人员 不知道如何使用 Adob e Flash CS4 有没有一种简单的方法可以将链接添加到 Flash 横幅 我有 flv 文件 其中包含库和两层中的一些项目 请给我一步一步的指示 编辑 我找到简单的解决方案 步骤如下 G
  • 放置项和对齐项有什么区别?

    想知道使用有什么区别 display flex align items center or display flex place items center 视觉上看起来是一样的 place items 有 90 的浏览器支持 align i
  • 具有 .htaccess 和 mod_rewrite 的静态 HTML 文件的语义 URL

    mod rewrite 总是让我困惑 谁能告诉我获得以下干净 URL 所需的规则 左边是所需的 URL 右边是真实的 URL our work gt our work html our work some project gt our wo
  • 使用 CORS 和 OpenShift 上的节点应用程序通过 POST 清空请求正文

    我正在 OpenShift 上使用 Express 创建一个简单的 Node 应用程序 我只是修改 OpenShift 的默认示例 Node 应用程序 我想要 CORS 支持 var cors require cors Initialize
  • 在Python中计算元音

    def main print count def countVowels string vowel aeiouAEIOU count 0 string input enter a string for i in string if i in
  • 文本区域和超链接?

    我有两个关于 Visual Studio 中的 C 的快速 简单的问题 首先 除了程序中的文本区域之外 是否有类似标签的东西 我想在我的程序中包含多行文本 但似乎只能使用打开自动换行的 DotNetBar 标签来完成它 其次 有没有办法在不
  • 是否存在任何危险,例如使用 pip 的 --ignore-installed 标志导致冲突?

    我无法找到 pip 的良好文档 ignore installed flag pip install help简单地说 忽略已安装的软件包 而是重新安装 除了系统上存在更多问题的副作用之外 因为安装的软件包在升级时不会被卸载 是否还有其他已知
  • PHP 评估 $a="$a"?

    我正在查看一些工作代码 并发现了这一行 eval element element 我真的很困惑为什么 PHP 开发人员会写这行代码 除了为自身设置一个变量之外 这还有什么目的 幸运的是 该行所在的函数从未被调用 上面的例子将输出 This
  • 在 Woocommerce 结帐页面中添加信息丰富的自定义消息

    我有一个基于 WP Woocommerce 的网站 我想告诉我的客户 每当他们在我的商店购买东西时 他们订单的 3 都会捐赠给慈善协会 我想显示根据总数计算的确切金额 例如 总计 150 欧元 5 欧元将被下放等 我该如何管理它 您可以将其
  • > 无法在 /opt/android-sdk-linux 中找到哈希字符串“android-26”的目标

    乌班图16 04 android sdk 位于 opt android sdk linux android home 配置 导出 ANDROID HOME opt android sdk linux opt android sdk linu
  • C++ 中真正的异步文件 IO

    我有一个超快的 M 2 驱动器 有多快 没关系 因为我无论如何也无法利用这个速度 这就是我问这个问题的原因 我有一个需要大量内存的应用程序 太多了 以至于内存装不下 幸运的是 并不是一下子就需要它 相反 它用于保存计算的中间结果 不幸的是
  • AdMob - Android 活动中的更好性能

    我有一个 Android 应用程序 我在其中实现了 AdMob 广告 我的布局代码非常简单 将 AdView 添加到 LinearLayout 中
  • 访问者模式对于动态类型语言有用吗?

    访问者模式允许在不扩展对象类的情况下编写对对象的操作 当然 但为什么不直接编写一个全局函数或静态类来从外部操作我的对象集合呢 基本上 在像 java 这样的语言中 accept 出于技术原因需要方法 但在一种语言中我可以实现相同的设计而无需