设计模式(十一)解释器模式
模式代码
// 抽象表达式 public abstract class AbstractExpression { /** * 抽象的解析方法 */ public abstract void interpret(Context ctx); } // 终结符表达式 public class TerminalExpression extends AbstractExpression { @Override public void interpret(Context ctx) { //实现文法中与终结符有关的解释操作 } } // 非终结符表达式 public class NonterminalExpression extends AbstractExpression { @Override public void interpret(Context ctx) { //实现文法中与非终结符有关的解释操作 } } // 上下文环境类,包含解释器之外的全局信息 public class Context { } // 客户类 public class Client { public static void main(String[] args) { //根据文法对特定句子构建抽象语法树后解释 } }
简单实现
需求:比如算数表达式 m + n + p。代表数字的m、n、p三个字符看成终结符号,+ 看做非终结符号。
1.抽象的算术运算解释器,为所有解释器共性的提取
public abstract class ArithmeticExpression { /** * 抽象的解析方法 * 具体的解析逻辑由具体的子类实现 * @return 解析得到具体的值 */ public abstract int interpret(); }
2.数字解释器,仅仅为了解释数字
public class NumExpression extends ArithmeticExpression{ private int num; public NumExpression(int num) { this.num = num; } @Override public int interpret() { return num; } }
3.运算符号抽象解释器,为所有运算符号解释器共性的提取
public abstract class OperatorExpression extends ArithmeticExpression { //声明两个成员变量存储运算符号两边的数字解释器 protected ArithmeticExpression exp1, exp2; public OperatorExpression(ArithmeticExpression exp1, ArithmeticExpression exp2) { this.exp1 = exp1; this.exp2 = exp2; } }
4.加法运算抽象解释器
public class AdditionExpression extends OperatorExpression { public AdditionExpression(ArithmeticExpression exp1, ArithmeticExpression exp2) { super(exp1, exp2); } @Override public int interpret() { return exp1.interpret() + exp2.interpret(); } }
5.处理与解释相关的一些业务
public class Calculator { //声明一个Stack栈存储并操作所有相关的解释器 private Stack<ArithmeticExpression> mExpStack = new Stack<>(); public Calculator(String expression) { //声明两个TerminalExpression类型的临时变量,存储运算符左右两边的数字解释器 ArithmeticExpression exp1, exp2; String[] elements = expression.split(" "); //循环遍历表达式元素数组 for (int i = 0; i < elements.length; i++) { //判断运算符号 switch (elements[i].charAt(0)) { case '+': //如果是加号 //将栈中的解释器弹出作为运算符号右边的解释器 exp1 = mExpStack.pop(); //同时将运算符号数组下标下一个元素构造为一个数字解释器 exp2 = new NumExpression(Integer.valueOf(elements[++i])); //通过尚明两个数字解释器构造加法运算解释器 mExpStack.push(new AdditionExpression(exp1, exp2)); break; default: //如果是数字 //直接构造数字解释器并压入栈 mExpStack.push(new NumExpression(Integer.valueOf(elements[i]))); break; } } } public int calculate() { return mExpStack.pop().interpret(); } }
6.客户类
public class Client { public static void main(String[] args) { Calculator calculator = new Calculator("1 + 2 + 3 + 10"); System.out.println(calculator.calculate()); } }
此时只是定义了加法运算,如果需要增加减法运算,则可以在 Calculator 中增加以下分支
case '-': //如果是减号 exp1 = mExpStack.pop(); exp2 = new NumExpression(Integer.valueOf(elements[++i])); mExpStack.push(new SubtractionExpression(exp1, exp2)); break;
此时,在 Client 中就可以开始使用了
public class Client { public static void main(String[] args) { Calculator calculator = new Calculator("1 - 2 - 3 + 10"); System.out.println(calculator.calculate()); } }