《设计模式》— 行为型模式 — 访问者模式

一、动机

考虑一个编译器,它将源程序表示为一个抽象语法树。该编译器需要在抽象语法书上实施某些操作以进行”静态语义“分析,例如检查所有的变量是否都已经被定义了。它也需要生成代码。因此它可能要定义许多操作以进行类型检查、代码优化、流程分析,检查变量是否在使用前被赋值等。此外,还可以使用抽象语法树进行格式梅花、程序重构、静态分析等功能。

这些操作大多要求对不同的节点进行不同的处理。例如,对代表赋值语句的节点的处理就不同于对代表变量或者算术表达式节点的处理。因此有用于赋值语句的类,有用于变量访问的类,还有用于算式表达式的类,等等。节点类的集合当然依赖于被编译的语言,但对于一个给定的语言其变化不大。

考虑下图所示的 Node 层次结构:
在这里插入图片描述
这里的问题是,将所有这些操作分配到各种节点类中会导致整个系统难以理解、难以维护和修改。将类型检查代码和代码生成功能放在一起,将产生混乱。此外,增加新的操作通常需要重新编译所有这些类。如果可以独立地增加新的操作,并且使这些节点类独立与作用于其上的操作,将会更好一些。

要实现上述两个目标,我们可以将每一个类中相关的操作包装在一个独立的对象中,并在遍历抽象语法树时将此对象传递给当前访问的元素。当一个元素“接受”该访问者时,该元素向访问者发送一个包含自身类信息的请求。该请求同时也将该元素本身作为一个参数。然后访问者将为钙元素执行该操作 —— 这一操作以前是在该元素的类中的。

例如,一个不使用访问者的编译器可能会通过在它的抽象语法树上调用 typeCheck 操作对一个过程进行类型检查。每一个节点将调用它的成员的 typeCheck 以实现自身的 typeCheck。如果该编译器使用访问者对一个过程进行类型检查,那么它将会创建一个 TypeCheckingVisitor 对象,并以这个对象为参数在抽象语法树上调用 accept 操作。每一个节点在实现 accept 时将会回调访问者:一个赋值节点调用访问者的 VisitAssignment 操作,而一个变量引用将调用 VisitVariableReference。类 AssignmentNodetypeCheck 操作现在称为 TypeCheckingVisitorVisitAssignment 操作。

为使访问者不仅仅做类型检查,我们需要所有抽象语法树的访问者you一个抽象的父类 NodeVisitorNodeVisitor 必须为每一个节点类定义一个操作。一个需要计算程序度量的应用将定义 NodeVisitor 的新的子类,并且将不再需要在

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值