概念:
解释器模式就是定义语言的文法,并定义一个解释器解释文中的句子。
在这里我们将语言理解成使用规定格式和语法的代码。
在前面我们知道可以构建解释器来解决那些频繁发生的某一特定类型的问题,在这我们将这些问题的实例表述为一个语言中句子。例如我经常利用正则表达式来检测某些字符串是否符合我们规定的格式。这里正则表达式就是解释器模式的应用,解释器为正则表达式定义了一个文法,如何表示一个特定的正则表达式,以及如何解释这个正则表达式。
解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发的编译器中。它描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。在解释器模式中除了能够使用文法规则来定义一个语言,还有通过一个更加直观的方法来表示——使用抽象语法树。抽象语法树能够更好地,更直观地表示一个语言的构成,每一颗抽象语法树对应一个语言实例
AbstractExpression: 抽象表达式。声明一个抽象的解释操作,该接口为抽象语法树中所有的节点共享。
TerminalExpression: 终结符表达式。实现与文法中的终结符相关的解释操作。实现抽象表达式中所要求的方法。文法中每一个终结符都有一个具体的终结表达式与之相对应。
NonterminalExpression: 非终结符表达式。为文法中的非终结符相关的解释操作。
Context: 环境类。包含解释器之外的一些全局信息。
Client: 客户类。
抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符和非终结符类。 在解释器模式中由于每一种终结符表达式、非终结符表达式都会有一个具体的实例与之相对应,所以系统的扩展性比较好。
interface Node { int interpret(); } class ValueNode implements Node { protected int value; public ValueNode(int value) { super(); this.value = value; } @Override public int interpret() { // TODO Auto-generated method stub return value; } } abstract class SymbolNode implements Node { protected Node left; protected Node right; public SymbolNode(Node left, Node right) { super(); this.left = left; this.right = right; } } class MulNode extends SymbolNode { public MulNode(Node left, Node right) { super(left, right); // TODO Auto-generated constructor stub } @Override public int interpret() { // TODO Auto-generated method stub return left.interpret() * right.interpret(); } } class DivNode extends SymbolNode{ public DivNode(Node left,Node right){ super(left,right); } public int interpret(){ return super.left.interpret() / super.right.interpret(); } } class Calculator { private String state; private Node node; public void build(String statement) { Node left = null, right = null; Stack<Node> stack = new Stack<>(); String[] arr = statement.split(" "); for (int i = 0; i < arr.length; i++) { if (arr[i].equals("*")) { left = stack.pop(); right = new ValueNode(Integer.parseInt(arr[++i])); Node node = new MulNode(left, right); stack.push(node); } else if (arr[i].equals("/")) { left = stack.pop(); right = new ValueNode(Integer.parseInt(arr[++i])); Node node = new MulNode(left, right); stack.push(node); } else { Node node = new ValueNode(Integer.parseInt(arr[i])); stack.push(node); } } this.node = stack.pop(); } public int compute() { return node.interpret(); } }
优点
1、 可扩展性比较好,灵活。
2、 增加了新的解释表达式的方式。
3、 易于实现文法。
缺点
1、 执行效率比较低,可利用场景比较少。
2、 对于复杂的文法比较难维护。
五、 模式适用场景
1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
2、一些重复出现的问题可以用一种简单的语言来进行表达。
3、文法较为简单。