解释器模式

/ 设计模式

解释器模式(interpreter)

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子

GoF23种设计模式中,属于行为型模式( Behavioral Patterns)

对于一种特定的高频发生的问题,我们就可以通过解释器模式应对,定义一个特定的语法,执行特定的解析从而减少问题的发生。

比如,我们开发中会遇到很多指标计算问题,日常编码是写死一个个的指标计算。这样的系统难以拓展,每增加新的指标,我们都要新增代码或修改之前的代码。

如果,我们定义一种新语法,来抽象指标的计算,把变量与计算符号分离,这样就可以动态配置指标计算,而不增加系统的复杂程度,类似groovy脚本SpEL表达式等。

实例

解释器模式总览

角色说明

举例

我们将设计一个简单加减运算表达式。

为了对计算机友好,我们表达式采用逆波兰表达式(也叫后缀表达式)。

通过解析逆波兰表达式,得到简单运算式的结果。

解释器模式举例

角色说明

code

public interface Expression {

    int interpreter(Context context);
}
public class MinusExpression implements Expression {

    private Expression left;

    private Expression right;

    public MinusExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }


    @Override
    public int interpreter(Context context) {
        return left.interpreter(context) - right.interpreter(context);
    }
}

public class PlusExpression implements Expression {

    private Expression left;

    private Expression right;

    public PlusExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }


    @Override
    public int interpreter(Context context) {
        return left.interpreter(context) + right.interpreter(context);
    }
}
public class KeyExpression implements Expression{

    private String variable;

    public KeyExpression(String variable) {
        this.variable = variable;
    }


    @Override
    public int interpreter(Context context) {
        return context.getValue(variable);
    }
}
public class ValueExpression implements Expression{

    private int value;

    public ValueExpression(int value) {
        this.value = value;
    }

    @Override
    public int interpreter(Context context) {
        return value;
    }
}

public class Context {

    private Map<String, Expression> interpreterMap;

    public Context(Map<String, Expression> interpreterMap) {
        this.interpreterMap = interpreterMap;
    }

    public int getValue(String key) {
        if (interpreterMap.containsKey(key)) {
            return interpreterMap.get(key).interpreter(this);
        }
        return 0;
    }

}
public class Evaluator {

    private final static String SEPARATOR = " ";
    private final static String PLUS = "+";
    private final static String MINUS = "-";


    public int parse(String expression) {
        Stack<Expression> expressionStack = new Stack<>();
        for (String token : expression.split(SEPARATOR)) {

            switch (token) {
                case PLUS:
                    Expression plusExpression = new PlusExpression(expressionStack.pop(), expressionStack.pop());
                    expressionStack.push(plusExpression);
                    break;
                case MINUS:
                    //栈后进先出,先出为右,后出为左
                    Expression right = expressionStack.pop();
                    Expression left = expressionStack.pop();
                    Expression minusExpression = new MinusExpression(left, right);
                    expressionStack.push(minusExpression);
                    break;
                default:
                    expressionStack.push(new ValueExpression(Integer.parseInt(token)));
            }
        }
        return expressionStack.pop().interpreter(null);
    }

    public int parse(String expression, Context context) {
        Stack<Expression> expressionStack = new Stack<>();
        for (String token : expression.split(SEPARATOR)) {

            switch (token) {
                case PLUS:
                    Expression plusExpression = new PlusExpression(expressionStack.pop(), expressionStack.pop());
                    expressionStack.push(plusExpression);
                    break;
                case MINUS:
                    Expression right = expressionStack.pop();
                    Expression left = expressionStack.pop();
                    Expression minusExpression = new MinusExpression(left, right);
                    expressionStack.push(minusExpression);
                    break;
                default:
                    expressionStack.push(new KeyExpression(token));
            }
        }
        return expressionStack.pop().interpreter(context);
    }

}
public class Client {
    public static void main(String[] args) {
        //语法执行器
        Evaluator evaluator = new Evaluator();

        //计算 5+10+42-12

        //标准执行
        String expression = "a b c d - + +";
        Map<String, Expression> expressionMap = new HashMap<>(16);
        expressionMap.put("a", new ValueExpression(5));
        expressionMap.put("b", new ValueExpression(10));
        expressionMap.put("c", new ValueExpression(42));
        expressionMap.put("d", new ValueExpression(12));
        int result = evaluator.parse(expression, new Context(expressionMap));
        System.out.println(result);

        //简化执行
        String expression1 = "5 10 42 12 - + +";
        int result1 = evaluator.parse(expression1);
        System.out.println(result1);
    }
}
45
45

实例

code:org.springframework.expression.Expression

public class Test {

   public static void main(String[] args) {
       SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
       org.springframework.expression.Expression expression = spelExpressionParser.parseExpression("100*2+200");
       int value = (int) expression.getValue();
       System.out.println(value); //output 400
   }
}

如果maven没有引入,请引入以下到pom中。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>

总结

解析器模式可以定义简单预发来解决高频特定问题。但是由于该模式难于维护,对于复杂的语言解析还需从长计议啊。