解释器模式

一、解释器模式介绍

1、定义与类型

定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
为了解释一种语言,而为语言创建的解释器
类型:行为型

2、适用场景

某个特定类型问题发生频率足够高

3、优点

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

4、缺点

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

5、相关设计模式

解释器模式和适配器模式
适配器模式是需要预先知道要适配的规则,解释器则是要把规则写好,根据规则执行解释

二、代码示例

模拟场景:模拟计算机解释计算表达式,例如中缀表达式 6 * (100 +11) ,计算机会先转换为后缀运算符 6 100 11 + * ,转换过程此处省略,再依次入栈,遇到运算符则出栈中的两个数字进行计算,再将计算结果入栈。
此处需要补充知识点:计算机如何计算我们的表达式的,可参考https://wenku.baidu.com/view/3ff189a15ef7ba0d4a733bb5.html中的表达式求值

解释器接口:

public interface Interpreter {
    int interpret();
}

数字解释器:

public class NumberInterpreter implements Interpreter {
    private int number;

    public NumberInterpreter(int number) {
        this.number = number;
    }

    public NumberInterpreter(String number) {
        this.number = Integer.valueOf(number);
    }

    @Override
    public int interpret() {
        return this.number;
    }
}

加法解释器:

public class AddInterpreter implements Interpreter {
    private Interpreter firstExpression, secondExpression;

    public AddInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public int interpret() {
        return this.firstExpression.interpret() + this.secondExpression.interpret();
    }

    @Override
    public String toString() {
        return "+";
    }
}

乘法解释器:

public class MultiInterpreter implements Interpreter {
    private Interpreter firstExpression, secondExpression;

    public MultiInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public int interpret() {
        return this.firstExpression.interpret() * this.secondExpression.interpret();
    }

    @Override
    public String toString() {
        return "*";
    }
}

运算符工具类:

public class OperatorUtil {
    public static boolean isOperator(String symbol) {
        return (symbol.equals("+") || symbol.equals("*"));
    }

    public static Interpreter getExpressionObject(Interpreter firstExpression, Interpreter secondExpression, String symbol) {
        if (symbol.equals("+")) {
            return new AddInterpreter(firstExpression, secondExpression);
        } else if (symbol.equals("*")) {
            return new MultiInterpreter(firstExpression, secondExpression);
        }
        return null;
    }
}

转换器类:

public class MyExpressionParser {
    private Stack<Interpreter> stack = new Stack<Interpreter>();

    public int parser(String str) {
        String[] strItemArray = str.split(" ");
        for (String symbol : strItemArray) {
            if (!OperatorUtil.isOperator(symbol)) {
                Interpreter numberExpression = new NumberInterpreter(symbol);
                stack.push(numberExpression);
                System.out.println(String.format("入栈:%d", numberExpression.interpret()));
            } else {
                // 是运算符,可以计算
                Interpreter firstExpression = stack.pop();
                Interpreter secondExpression = stack.pop();
                System.out.println(String.format("出栈:%d 和 %d", firstExpression.interpret(), secondExpression.interpret()));
                Interpreter operator = OperatorUtil.getExpressionObject(firstExpression, secondExpression, symbol);
                System.out.println(String.format("应用运算符:%s", operator));
                int result = operator.interpret();
                NumberInterpreter resultExpression = new NumberInterpreter(result);
                stack.push(resultExpression);
                System.out.println(String.format("阶段结果入栈:%d", resultExpression.interpret()));
            }
        }
        int result = stack.pop().interpret();
        return result;
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        String inputStr = "6 100 11 + *";
        MyExpressionParser expressionParser = new MyExpressionParser();
        int result = expressionParser.parser(inputStr);
        System.out.println(result);
    }
}

输出:
入栈:6
入栈:100
入栈:11
出栈:11 和 100
应用运算符:+
阶段结果入栈:111
出栈:111 和 6
应用运算符:*
阶段结果入栈:666
666

三、源码示例

1、JDK中的正则Pattern

2、spring中的El表达式

测试:

public class SpringTest {
    public static void main(String[] args) {
        org.springframework.expression.ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("6 * (100 + 11)");
        int result = (Integer) expression.getValue();
        System.out.println(result);
    }
}

输出:666

posted @ 2020-06-18 07:25  weixiaokun  阅读(218)  评论(0编辑  收藏  举报