设计模式之解释器模式

四则运算问题

通过解释器模式来实现四则运算,如计算a+b-c的值,具体要求 :

  1. 先输入表达式的形式,比如 a+b+c-d+e,要求表达式的字母不能重复。
  2. 再分别输入a,b,c,d,e的值。
  3. 最后输出运算结果。

解释器模式

基本介绍
  1. 在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树。这里的词法分析器和语法分析器都可以看作是解释器。
  2. 解释器模式:是指给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器,是用该解释器来解释语言中的句子(表达式)。
    设计模式之解释器模式
解释器模式解决四则运算问题

为了实现方便,并简化问题。我们只引入加法和减法。

  1. UML类图
    设计模式之解释器模式
  2. 代码实现
    Expression 类:
    import java.util.HashMap;
    
    public abstract class Expression {
        public abstract int interpreter(HashMap<String, Integer> var);
    }
    
    变量解释器 VarExpression 类:
    import java.util.HashMap;
    
    /**
     * 变量的解释器
     */
    public class VarExpression extends Expression {
    
        private String key;
    
        public VarExpression(String key) {
            this.key = key;
        }
    
        @Override
        public int interpreter(HashMap<String, Integer> var) {
            return var.get(this.key);
        }
    }
    
    符号表达式 SymbolExpression 类:
    import java.util.HashMap;
    
    public class SymbolExpression extends Expression{
    
        protected Expression left;
        protected Expression right;
    
        public SymbolExpression(Expression left, Expression right) {
            this.left = left;
            this.right = right;
        }
    
        @Override
        public int interpreter(HashMap<String, Integer> var) {
            return 0;
        }
    }
    
    加法符号 AddExpression 类:
    import java.util.HashMap;
    
    public class AddExpression extends SymbolExpression {
    
        public AddExpression(Expression left, Expression right) {
            super(left, right);
        }
    
        public int interpreter(HashMap<String, Integer> var) {
            return super.left.interpreter(var) + super.right.interpreter(var);
        }
    }
    
    减法符号 SubExpression 类:
    import java.util.HashMap;
    
    public class SubExpression extends SymbolExpression {
    
        public SubExpression(Expression left, Expression right) {
            super(left, right);
        }
    
        public int interpreter(HashMap<String, Integer> var) {
            return super.left.interpreter(var) - super.right.interpreter(var);
        }
    }
    
    Calculator 计算器类:
    import java.util.HashMap;
    import java.util.Stack;
    
    public class Calculator {
    
        private Expression expression;
    
        public Calculator(String expStr) {
            Stack<Expression> stack = new Stack<>();
    
            char[] charArray = expStr.toCharArray();
    
            Expression left = null;
            Expression right = null;
    
            for (int i = 0; i < charArray.length; ++i) {
                switch (charArray[i]) {
                    case '+':
                        left = stack.pop();
                        right = new VarExpression(String.valueOf(charArray[++i]));
                        stack.push(new AddExpression(left, right));
                        break;
                    case '-':
                        left = stack.pop();
                        right = new VarExpression(String.valueOf(charArray[++i]));
                        stack.push(new SubExpression(left, right));
                        break;
                    default:
                        stack.push(new VarExpression(String.valueOf(charArray[i])));
                        break;
                }
            }
            this.expression = stack.pop();
        }
    
        public int run(HashMap<String, Integer> var) {
            return this.expression.interpreter(var);
        }
    }
    
    Client 类:
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.HashMap;
    
    public class Client {
    
        public static void main(String[] args) throws IOException {
    
            String expStr = getExpStr();
            HashMap<String, Integer> var = getValue(expStr);
    
            Calculator calculator = new Calculator(expStr);
            System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
        }
    
        private static HashMap<String, Integer> getValue(String expStr) throws IOException {
    
            HashMap<String, Integer> map = new HashMap<>();
    
            for (char ch: expStr.toCharArray()) {
                if (ch != '+' && ch != '-') {
                    if (!map.containsKey(String.valueOf(ch))) {
                        System.out.println("请输入" + String.valueOf(ch) + "的直:");
                        String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
                        map.put(String.valueOf(ch), Integer.valueOf(in));
                    }
                }
            }
            return map;
        }
    
        private static String getExpStr() throws IOException {
            System.out.println("请输入表达式:");
            return (new BufferedReader(new InputStreamReader(System.in))).readLine();
        }
    }
    

解释器模式在Spring框架中的应用

例如:

public class Main {
    public static void main(String[] args) {
        SpelExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("10 * (2 + 1) * 1 + 66");
        int result = (Integer) expression.getValue();
        System.out.println(result);
    }
}
  1. UML类图
    设计模式之解释器模式
  2. 总结
    1. Expression是一个表达式接口,下面有不同的实现类,如SpelExpression。
    2. 使用的时候,根据创建的不同的 ExpressionParser(如InternalSpelExpressionParser或SpelExpressionParser)对象,返回不同的表达式Expression对象。
    3. getValue()方法是一个解释器方法。不同的Expressioin调用getValue方法,解释表达式,得到结果。

解释器模式的注意事项和细节

  1. 当一个语言需要解释执行,可以将该语言中的句子表示为一个抽象的语法树,就可以考虑使用解释器模式,让程序具有良好的扩展性。
  2. 应用场景:编译器、运算表达式计算、正则表达式、机器人等。
  3. 使用解释器可能带来的问题:解释器模式会引起类膨胀、解释器模式采用递归调用方法,将可能导致调式空难,执行效率低。
上一篇:行为型模式 - 解释器模式


下一篇:Java 中控制执行流程