设计模式拾荒之解释器模式: 最不容易实现的设计模式

  1. 参考书籍: 《Design Patterns: Elements of Reusable Object-Oriented Software》

设计模式用前须知

  • 设计模式种一句出现频率非常高的话是,“ 在不改动。。。。的情况下, 实现。。。。的扩展“ 。
  • 对于设计模式的学习者来说,充分思考这句话其实非常重要, 因为这句往往只对框架/ 工具包的设计才有真正的意义。因为框架和工具包存在的意义,就是为了让其他的程序员予以利用, 进行功能的扩展,而这种功能的扩展必须以不需要改动框架和工具包中代码为前提
  • 对于应用程序的编写者, 从理论上来说, 所有的应用层级代码至少都是处于可编辑范围内的, 如果不细加考量, 就盲目使用较为复杂的设计模式, 反而会得不偿失, 毕竟灵活性的获得, 也是有代价的。

解释器模式(Interpreter Pattern)

  • 设计意图
    • 给定一个语言后, 为该语言定义一种语法, 同时再定义一个解释器, 该解释器会按照定义的语法来解释该语言中的语句。
  • GoF 举例

    • 当一类问题经常反复出现时, 那么就可能值得去设计一个自定义的语言, 用于表达该问题, 并定义一个解释器,理解自定义语言表达的问题并解决问题。 正则表达式就是一个很好的例子。 正则表达式是一种用于描述字符串模式的标准语言。 与其为每种字符串模式编写特定的匹配算法, 不如设计一种查找算法可以理解正则表达式, 按照正则表达式所描述的模式去匹配字符串。
  • 解决方案

    • 解释器模式描述了如何为一门简单的语言定义语法, 如何表示该语言中的语句, 以及如何解释这些语句。 在下面的这个例子中, 解释器模式将会描述如何为正则表达式定义语法, 如何表示一个正则表达式, 以及如何解释这个正则表达式。
    • 现在假设下列的语法定义了正则表达式。

      expression ::= literal | alternation | sequence | repetition |
      '(' expression ')'
      alternation ::= expression '|' expression
      sequence ::= expression '&' expression
      repetition ::= expression '*'
      literal ::= 'a' | 'b' | 'c' | ... { 'a' | 'b' | 'c' | ... }*
      • Tips: 上面的这种语法定义方式对于在大学时期学过编译原理,或者翻看过编译原理书籍的同志会比较熟悉。本例中, “::=”是定义符号,表示左侧的东西被“定义为”右侧的东西。 “ | ”表示“或”。“ & ”表示 “连接”
    • 解释器模式会为每一条语法规则定义一个类来表示该语法规则。如下图所示
    • 每一个按照该语法定义的正则表达式都会被一个由上述类实例构成的抽象语法树, 例如 ,正则表达式 raining & (dogs | cats)* 就会被表示成下图的结构。
    • 我们可以在这些 RegularExpression 的子类中实现 interpret() 方法 , 为这些表达式创建解释器 。 每一个 RegularExpression 的子类的 Interpret 方法可以通过一个 Context 对象获取它所需要的上下文信息(待匹配的字符串, 整个表达式到目前为止被匹配了多少), 例如
      • LiteralExpression 会检查输入是否符合 literal 的定义
      • AlternationExpression 会检查输入是否匹配 alternation1 , alternation2 中的任意一个表达式
      • RepeationExpression 会检查输入是否包含它所持有的实例 RegularExpression 的多个重复匹配。

应用场景

  • 解释器模式的确是在描述如何实现一个语言的语法表达, 以及如何解释它。 但解释器模式最好是在如下情形使用:
    • 要定义的语言有较为简单的语法。当语法比较复杂时, 用于表达语法的类的层级结构会变得很大且难以管理。此时, 去借助一些解释器生成工具更为合适。
    • 应用对语言解释的效率要求不苛刻。 最有效率的解释器通常并不会以直接解析语法树的方式去实现, 而是会首先将语法树转换为其它形式。 例如, 正在表达式通常会先被转换成状态机的模式, 但是即便如此, 这种转换工具也可以用解释器模式去实现, 所以解释器模式在这个意义上, 依旧是适用的。

结构图

总结

  • 解释器模式可能对于80%的程序员来说没有什么应用机会。原因是它在教你怎么使用面向对象的语言来实现一些自定义的语言, 以及自定义语言的解释器来解释你所定义的语言。 但是了解该模式的作用还是很有意义的,万一哪天真的需要在自己的应用中定义一些简单的语言来表达和解决一些问题时, 至少提供了解决问题的一个重要思路

你可能感兴趣的:(设计模式)