大白话聊访问者模式:从入门到实践 (3)

ClassReader 类相当于访问者模式中的 Element 元素。它将字节数组或 class 文件读入内存中,并以树的数据结构表示。该类定义了一个 accept 方法用来和 visitor 交互。

大白话聊访问者模式:从入门到实践

ClassVisitor 相当于抽象访问者接口。ClassReader 对象创建之后,需要调用 accept() 方法,传入一个 ClassVisitor 对象。在 ClassReader 的不同时期会调用 ClassVisitor 对象中不同的 visit() 方法,从而实现对字节码的修改。

ClassWriter 是 ClassVisitor 的是实现类,它负责将修改后的字节码输出为字节数组。

对于 ASM 这种场景而言,字节码规范是非常严格且稳定的,如果随便更改可能出问题。但我们又需要对字节码进行动态修改,从而达到某些目的。在这种情况下,ASM 的设计者采用了访问者模式将变化的部分隔离开来,将不变的部分固定下来,从而达到了灵活扩展的目的。

03 我们该如何使用?

从上面几个例子,我们大致可以明白访问者模式的使用场景:某些较为稳定的东西(数据结构或算法),不想直接被改变但又想扩展功能,这时候适合用访问者模式。

说到对于访问者模式使用场景的定义,我们会觉得模板方法模式与这个使用场景的定义很像。但它们还是有些许差别的。访问者模式的变化与非变化(即访问者与被访问者)之间,它们只是简单的包含关系,而模板方法模式的变化与非变化则是继承关系。 但它们也确实有类似的地方,即都是封装了固定不变的东西,开放了变动的东西。

访问者模式的优点很明显,即隔离了变化的东西,固定了不变的东西,使得整体的可维护性更强、具有更强的扩展性。但它也带来了设计模式通用的一些缺点,例如:

类结构变得复杂。之前我们可是简单的调用关系,现在则是多个类之间的继承和组合关系。从一定程度上,提高了对开发人员的要求,提高了研发成本。

被访问者的变更变得更加困难。例如我们上面科学家访谈的例子,如果科学家访谈希望新增一个环节,那么 Scientist 类需要修改,Visitor 类、XinhuaVisitor 类都需要修改。

有这些多优点,但也有这么多缺点,那实际工作中我们应该怎么判断是否用访问者模式呢?

总的原则就是扬长避短,即当场景完全利用了访问者模式的优点,规避了访问者模式的缺点的时候,就是使用访问者模式的最佳时机。

虽然使用访问者模式会让被访问者的变更变得更加困难,但如果被访问者很稳定,基本不会变更,那这个缺点不就去除了么。例如在 ASM 的例子中,元素是 ClassReader,其存储了字节码的结构。而字节码结构完全不会轻易改变,所以在这个「被访问者的变更变得更加困难」的缺点也就不存在了。

而「类结构变得复杂」这个缺点,则是需要根据当时业务的复杂程度来看的。如果当时业务很简单,而且变化也不大,那么使用设计模式完全是多余的。但是如果当时业务很复杂了,我们还是在一个类里做修改,那么很大可能性会出大问题。这时候就需要用设计模式来承载复杂的业务结构了。

04 参考资料

一文说透访问者模式 - 犀牛饲养员博客

访问者设计模式

访问者模式一篇就够了 - 简书

一文说透访问者模式 - 犀牛饲养员博客

访问者模式在 ASM 框架中的使用

访问者模式由浅入深及用例场景 加上 AMS 的简单使用_a1032722788 的博客 - CSDN 博客

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzsxy.html