zoukankan      html  css  js  c++  java
  • 解释器模式

    一、解释器模式介绍

    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

  • 相关阅读:
    收集Linux常用命令
    loadrunner没有告诉你的
    loadrunner没有告诉你的
    loadrunner没有告诉你的
    QA、EPG、PMO各自的职能划分及关系是什么?
    QA、EPG、PMO各自的职能划分及关系是什么?
    QA、EPG、PMO各自的职能划分及关系是什么?
    loadrunner通过odbc测mysql数据库语句
    loadrunner通过odbc测mysql数据库语句
    loadrunner通过odbc测mysql数据库语句
  • 原文地址:https://www.cnblogs.com/weixk/p/13155626.html
Copyright © 2011-2022 走看看