《Head First 设计模式》笔记20-解释器模式
定义
解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、正则表达式、符号处理引擎等。
模式结构
解释器模式主要包含如下几个角色:
AbstractExpression: 抽象表达式。声明一个抽象的解释操作,该接口为抽象语法树中所有的节点共享。
TerminalExpression: 终结符表达式。实现与文法中的终结符相关的解释操作。实现抽象表达式中所要求的方法。文法中每一个终结符都有一个具体的终结表达式与之相对应。
NonterminalExpression: 非终结符表达式。为文法中的非终结符相关的解释操作。
Context: 环境类。包含解释器之外的一些全局信息。
Client: 客户类。
抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符和非终结符类。 在解释器模式中由于每一种终结符表达式、非终结符表达式都会有一个具体的实例与之相对应,所以系统的扩展性比较好。
模式实现
现在我们用解释器模式来实现一个基本的加、减、乘、除和求模运算。例如用户输入表达式 3 * 4 / 2 % 4
,输出结果为 2。下图为该实例的 UML 结构图:
抽象表达式:Node.java。
public interface Node {
public int interpret();
}
非终结表达式:ValueNode.java。主要用解释该表达式的值。
public class ValueNode implements Node {
private int value;
public ValueNode(int value) {
this.value=value;
}
public int interpret() {
return this.value;
}
}
终结表达式抽象类,由于该终结表达式需要解释多个运算符号,同时用来构建抽象语法树:
public abstract class SymbolNode implements Node {
protected Node left;
protected Node right;
public SymbolNode(Node left,Node right) {
this.left=left;
this.right=right;
}
}
MulNode.java
public class MulNode extends SymbolNode {
public MulNode(Node left,Node right) {
super(left,right);
}
public int interpret() {
return left.interpret() * right.interpret();
}
}
ModNode.java
public class ModNode extends SymbolNode {
public ModNode(Node left,Node right) {
super(left,right);
}
public int interpret() {
return super.left.interpret() % super.right.interpret();
}
}
DivNode.java
public class DivNode extends SymbolNode {
public DivNode(Node left,Node right) {
super(left,right);
}
public int interpret() {
return super.left.interpret() / super.right.interpret();
}
}
Calculator.java
public class Calculator{
private String statement;
private Node node;
public void build(String statement){
Node left=null,right=null;
Stack stack=new Stack();
String[] statementArr=statement.split(" ");
for (int i=0; i<statementArr.length; i++) {
if (statementArr[i].equalsIgnoreCase("*")) {
left=(Node)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new MulNode(left,right));
} else if (statementArr[i].equalsIgnoreCase("/")) {
left=(Node)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new DivNode(left,right));
} else if(statementArr[i].equalsIgnoreCase("%")) {
left=(Node)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new ModNode(left,right));
} else {
stack.push(new ValueNode(Integer.parseInt(statementArr[i])));
}
}
this.node=(Node)stack.pop();
}
public int compute()
return node.interpret();
}
}
客户端:Client.java
public class Client{
public static void main(String args[]){
String statement = "3 * 2 * 4 / 6 % 5";
Calculator calculator = new Calculator();
calculator.build(statement);
int result = calculator.compute();
System.out.println(statement + " = " + result);
}
}
运行结果:3 * 2 * 4 / 6 % 5 = 4
优缺点
优点
- 可扩展性比较好,灵活。
- 增加了新的解释表达式的方式。
- 易于实现文法。
缺点
- 执行效率比较低,可利用场景比较少。
- 解释器模式为文法中的每一条规则至少定义了一个类,因此包含了许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其它的技术如语法分析程序或编译器生成器来处理。
参考
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com
文章标题:《Head First 设计模式》笔记20-解释器模式
文章字数:925
本文作者:Bin
发布时间:2018-08-04, 13:17:57
最后更新:2019-08-06, 00:07:35
原始链接:http://coolview.github.io/2018/08/04/Head-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E3%80%8AHead-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%8B%E7%AC%94%E8%AE%B020-%E8%A7%A3%E9%87%8A%E5%99%A8%E6%A8%A1%E5%BC%8F/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。