【设计模式】解释器模式

star2017 1年前 ⋅ 739 阅读

简介

为了解释一种语言,而为语言创建的解释器,例如需要指定一些复杂的搜索表达式,如果直接在类里面实现是不灵活的,当需要改变表达式的时候会比较麻烦。可以通过Expression类来定义一个简单的语法,并且实现interpret()方法。由Expression实例通过抽象语法树(AST- abstract syntax tree)来表达一个语法中的句子,通过调用AST上的interpret()方法来解释一个句子。该模式属于行为型。

适用场景

1、某个特定类型问题发生频率足够高
2、为简单的语言定义语法,语言中的句子可以被解释了
3、指定数据库语言如SQL
4、编写计算器语言

优点

1、语法由很多类表示,容易改变及扩展此“语言”

缺点

1、语法规则数目太多时,增加了系统复杂度

代码示例

image.png

public class Interpreter {
    @FunctionalInterface
    public interface Expr {
        int interpret(Map<String, Integer> context);

        static Expr number(int number) {
            return context -> number;
        }

        static Expr plus(Expr left, Expr right) {
            return context -> left.interpret(context) + right.interpret(context);
        }

        static Expr minus(Expr left, Expr right) {
            return context -> left.interpret(context) - right.interpret(context);
        }

        static Expr variable(String name) {
            return context -> context.getOrDefault(name, 0);
        }
    }
    private static Expr parseToken(String token, ArrayDeque<Expr> stack) {
        Expr left, right;
        switch(token) {
            case "+":
                right = stack.pop();
                left = stack.pop();
                return Expr.plus(left, right);
            case "-":
                right = stack.pop();
                left = stack.pop();
                return Expr.minus(left, right);
            default:
                return Expr.variable(token);
        }
    }
    public static Expr parse(String expression) {
        ArrayDeque<Expr> stack = new ArrayDeque<Expr>();
        for (String token : expression.split(" ")) {
            stack.push(parseToken(token, stack));
        }
        return stack.pop();
    }
}

测试类

public class InterpreterTest {
    public static void main(String[] args) {
        Interpreter.Expr expr = Interpreter.parse("w x z - +");
        Map<String, Integer> context = new HashMap<>();
        context.put("w",5);
        context.put("x",10);
        context.put("z",42);
        int result = expr.interpret(context);
        System.out.println(result);
    }
}

输出结果为:

-27

上面示例源码

源码分析

jdk中应用

Pattern是对正则的语法进行解释,正则就是一种语法。

Pattern pattern = Pattern.compile("[^0-9]");
Matcher matcher = pattern.matcher(title);
String all = matcher.replaceAll("");

spring中应用

SpelExpressionParser是对spring中的SpEL语法进行解释。

 String expressionStr = "1+2";
 ExpressionParser parser = new SpelExpressionParser();
 Expression expression = parser.parseExpression(expressionStr);
 Integer val = expression.getValue(Integer.class);
 System.out.println(expressionStr + "的结果是:" + val);
本文为博主原创文章,未经博主允许不得转载。
更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: