今天我们来学习解释器模式,比起命令模式,解释器模式更加小众,只会在一些特定的领域会被用到,比如编译器、规则引擎、正则表达式。所以,解释器模式也不是学习的重点,稍微了解一下。
概述解释器模式:(Interpreter Design Pattern)解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器用来处理这个语法。
今天要学习的解释器模式,其实就是用来实现根据语法规则解读“句子”的解释器。
何时使用:
- 如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
UML 类图:
角色组成:
-
Abstractexpression:定义解释器的接口,约定解释器的解释 *** 作。
-
Terminalexpression:终结符解释器,用来实现语法规则中和终结符相关的 *** 作,不再包含其它的解释器,如果用组合模式来构建抽象语法树的话,就相当于组合模式中的叶子对象,可以有多种终结符解释器。
-
Nonterminalexpression:非终结符解释器,用来实现语法规则中非终结符相关的 *** 作,通常一个解释器对应一个语法规则,可以包含其它的解释器,如果用组合模式来构建抽象语法树的话,就相当于组合模式中的组合对象,可以有多种非终结符解释器。
-
Context:上下文,通常包含各个解释器需要的数据,或是公共的功能。
-
Client:客户端,指的是使用解释器的客户端,通常在这里去把按照语言的语法做的表达式,转换成为使用解释器对象描述的抽象语法树,然后调用解释 *** 作。
Context环境角色
public class Context { private String input; private String output; public String getInput() { return input; } public void setInput(String input) { this.input = input; } public String getOutput() { return output; } public void setOutput(String output) { this.output = output; } }
抽象表达式
public abstract class Abstractexpression { public abstract void interpret(Context ctx); }
终结符表达式
public class Terminalexpression extends Abstractexpression{ public void interpret(Context ctx) { //实现与语法规则中的终结符相关联的解释 *** 作 System.out.println("终结符表达式"); } }
非终结符表达式
public class Nonterminalexpression extends Abstractexpression{ public void interpret(Context ctx) { //实现与语法规则中的非终结符相关联的解释 *** 作 System.out.println("非终结符表达式"); } }
Client客户端
public class Client { public static void main(String[] args) { Context context = new Context(); List list = new ArrayList<>(); list.add(new Terminalexpression()); list.add(new Nonterminalexpression()); list.add(new Terminalexpression()); for (Abstractexpression abstractexpression : list) { abstractexpression.Interpret(context); } } }
其中list为一个语法容器,容纳一个具体的表达式。通常Client是一个封装类,封装的结果就是传递进来一个规范语法文件,解析器分析后产生结果并返回,避免了调用者与语法分析器的耦合关系。
结果:
总结终结符表达式
非终结符表达式
终结符表达式
为什么会有这个解释器模式呢,从编译原理中可以受到一些启发,使用了这样的一个解释器可以在Java语言之上再定义一层语言,这种语言通过Java编写的解释器可以放到Java环境中去执行,这样如果用户的需求发生变化,比如打算做其他事情的时候,只用在自己定义的新的语言上进行修改,对于Java编写的代码不需要进行任何的修改就能在Java环境中运行,这是非常有用的。这就好像,虽然不管怎么编译,最终由中间代码生成最终代码(机器码)是依赖于相应的机器的。但是编译器却能理解高级语言和低级语言,无论高级语言的程序是怎么样编写的,编译器的代码是不用修改的,而解释器模式就是想做一个建立在Java和我们自定义语言之间的编译器。
解释器模式的代码实现比较灵活,没有固定的模板。我们前面说过,应用设计模式主要是应对代码的复杂性,解释器模式也不例外。它的代码实现的核心思想,就是将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。一般的做法是,将语法规则拆分一些小的独立的单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)