-
解释器模式就是定义语言的文法,并且建立一个解释器来解释该语言中的句子
-
解释器模式的UML图
-
AbstractExpression抽象表达式。TerminalExpression,终结符表达式,解释结果的;NonterminalExpression,非终结符表达式,一般以子类的形式出现;Context,环境类,存储符号和其他信息,以便于获取解释结果之前的存储;Client客户类
-
解释器模式通过将表达式转化成语法树,然后逐级计算得到最终计算的结果
-
解释器模式的代码实现
-
创建一个抽象解释器接口
/** * 抽象解释器,提供了元素与元素之间的计算方式以及计算过程 */ public interface Node { int interpret(); }
-
创建终结解释器类并实现抽象解释器
/** * 终结解释器(返回最终的结果),这个Node能够代表数学表达式中数字部分的展现 */ public class ValueNode implements Node { private int value; public ValueNode(int value) { this.value = value; } @Override public int interpret() { return this.value; } }
-
创建非终结解释器抽象类实现抽象解释器
/** * 非终结解释器 */ public abstract class SymbolNode implements Node { /** * 非终结解释器需要关联Node,并且分为左Node和右Node */ Node nodeLeft; Node nodeRight; public SymbolNode(Node nodeLeft, Node nodeRight) { this.nodeLeft = nodeLeft; this.nodeRight = nodeRight; } }
-
创建三个具体的非终结解释器
/** * 除法解释器(具体非终结解释器) */ public class DivSymbolNode extends SymbolNode { public DivSymbolNode(Node nodeLeft, Node nodeRight) { super(nodeLeft, nodeRight); } @Override public int interpret() { return nodeLeft.interpret() / nodeRight.interpret(); } }
/** * 取余解释器(具体非终结解释器) */ public class ModSymbolNode extends SymbolNode { public ModSymbolNode(Node nodeLeft, Node nodeRight) { super(nodeLeft, nodeRight); } @Override public int interpret() { return nodeLeft.interpret() % nodeRight.interpret(); } }
/** * 乘法解释器(具体非终结解释器) */ public class MulSymbolNode extends SymbolNode { public MulSymbolNode(Node nodeLeft, Node nodeRight) { super(nodeLeft, nodeRight); } @Override public int interpret() { return nodeLeft.interpret() * nodeRight.interpret(); } }
-
创建Context类
import java.util.Stack; /** * 结合了Context类并且为客户端提供了统一调用接口 * 这个类是核心解释器 * 计算是从孙子节点里的interpret */ public class Caculator { private Node node; /** * 待解释的语句 */ private String statement; /** * 解释可计算公式,将最终解释的结果存如stack中 * 最终需要将Node存储到stack中(在存储之前已经确定了表达式的顺序,解释完成的结果) * @param statement */ public void build(String statement){ //结合了非终结解释器 Node left = null; Node right = null; Stack stack = new Stack(); //context类 String[] statementArr = statement.split(" "); for (int i = 0; i < statementArr.length; i++) { if(statementArr[i].equals("*")){ left = (Node) stack.pop(); //获取栈顶元素,并且移除栈顶元素 int val = Integer.parseInt(statementArr[++i]); right = new ValueNode(val); stack.push(new MulSymbolNode(left, right)); //MulSymbolNode代表乘号 } else if(statementArr[i].equals("/")){ left = (Node) stack.pop(); int val = Integer.parseInt(statementArr[++i]); right = new ValueNode(val); stack.push(new DivSymbolNode(left, right)); //MulSymbolNode代表除号 } else if(statementArr[i].equals("%")){ left = (Node) stack.pop(); int val = Integer.parseInt(statementArr[++i]); right = new ValueNode(val); stack.push(new ModSymbolNode(left, right)); //MulSymbolNode代表取余 } else { stack.push(new ValueNode(Integer.parseInt(statementArr[i]))); //传入的数字 } } this.node = (Node) stack.pop(); //这个Node包含了所有的数字和符号 } /** * 计算build中解释的最终结果,并返回结果 * @return */ public int compute(){ return node.interpret(); } }
-
创建测试类
public class Test { public static void main(String[] args) { String statement = "3 * 2 * 4 / 3 % 5"; Caculator caculator = new Caculator(); caculator.build(statement); System.out.println(statement +" = " + caculator.compute()); } }
-
-
解释器模式的优点
- 扩展性比较好,灵活
- 增加了新的解释表达式的方式
- 易于实现文法
-
解释器模式的缺点
- 执行效率比较低,可使用场景较小
- 对于复杂的文法比较难维护
-
解释器模式的使用场景
- 讲一个需要解释执行的语句转成一个抽象语法树
- 一些重复出现的问题可以用一种简单的语句来进行表达
- 文法较为简单
-
JDK中对解释器模式的使用
设计模式--解释器模式
最新推荐文章于 2024-08-29 17:15:49 发布