中介者模式与解释器模式(3)

简介: 中介者模式与解释器模式(3)

创建数字表达式类:


public class NumInterpreter implements IArithmeticInterpreter {
    private int value;
    public NumInterpreter(int value) {
        this.value = value;
    }
    public int interpret() {
        return this.value;
    }
}


创建计算器类:不在乎乘除与加减得顺序,这都是解释器按照语义得解释,本案例中按照顺序执行


public class Calculator {
    private Stack<IArithmeticInterpreter> stack = new Stack<IArithmeticInterpreter>();
    public Calculator(String expression) {
        this.parse(expression);
    }
    private void parse(String expression) {
        String [] elements = expression.split(" ");
        IArithmeticInterpreter leftExpr, rightExpr;
        for (int i = 0; i < elements.length ; i++) {
            String operator = elements[i];
            if (OperatorUtil.isOperator(operator)){
                leftExpr = this.stack.pop();
                rightExpr = new NumInterpreter(Integer.valueOf(elements[++i]));
                System.out.println("出栈: " + leftExpr.interpret() + " 和 " + rightExpr.interpret());
                this.stack.push(OperatorUtil.getInterpreter(leftExpr, rightExpr,operator));
                System.out.println("应用运算符: " + operator);
            }
            else{
                NumInterpreter numInterpreter = new NumInterpreter(Integer.valueOf(elements[i]));
                this.stack.push(numInterpreter);
                System.out.println("入栈: " + numInterpreter.interpret());
            }
        }
    }
    public int calculate() {
        return this.stack.pop().interpret();
    }
}


操作工具类:


public class OperatorUtil {
    public static boolean isOperator(String symbol) {
        return (symbol.equals("+") || symbol.equals("-") || symbol.equals("*"));
    }
    public static AbstractInterpreter getInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right, String symbol) {
        if (symbol.equals("+")) {
            return new AddInterpreter(left, right);
        } else if (symbol.equals("-")) {
            return new SubInterpreter(left, right);
        } else if (symbol.equals("*")) {
            return new MultiInterpreter(left, right);
        } else if (symbol.equals("/")) {
            return new DivInterpreter(left, right);
        }
        return null;
    }
}


测试类:


public class Test {
    public static void main(String[] args) {
        System.out.println("result: " + new Calculator("10 + 30").calculate());
        System.out.println("result: " + new Calculator("10 + 30 - 20").calculate());
        System.out.println("result: " + new Calculator("100 * 2 + 400 * 1 + 66").calculate());
    }
}


六、解释器模式的优缺点

优点:

扩展性强:在解释器模式中由于语法是由很多类表示的,当语法规则更改时,只需修改相应的非终结符表达式即可;若扩展语法时,只需添加相应非终结符类即可;

增加了新的解释表达式的方式;

易于实现文法:解释器模式对应的文法应当是比较简单且易于实现的,过于复杂的语法并不适合使用解释器模式。


缺点:

语法规则较复杂时,会引起类膨胀:解释器模式每个语法都要产生一个非终结符表达式当语法规则比较复杂时,就会产生大量的解释类,增加系统维护困难;

执行效率比较低:解释器模式采用递归调用方法,每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,因此完整表达式的最终结果是通过从后往前递归调用的方式获取得到。当完整表达式层级较深时,解释效率下降,且出错时调试困难,因为递归迭代层级太深。


七、解释器模式在Spring源码中的应用

在 Spring 中,ExpressionParser 接口内部采用的也是解释器模式,它封装了字符串表达式的语法,源码如下。


package org.springframework.expression;
public interface ExpressionParser {
    Expression parseExpression(String expressionString) throws ParseException;
    Expression parseExpression(String expressionString, ParserContext context) throws ParseException;
}


ExpressionParser 不知道大家有没有用过,这里面也可以进行加减乘除运算。这里我们不深入讲解源码。如下是一个简单的应用示例:


package net.biancheng.c.interpreter;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class Test {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("100*2+400*1+66");
        int result = (Integer) expression.getValue();
        System.out.println("计算结果是:" + result);
    }
}


运行结果如下


计算结果是:666


由运行结果可以看到,运行结果与预期结果是一致的。

解释器模式一般在业务开发中用的相对较少,常用的表达式都有人解析好了,直接用就可以了,除非我们从事底层开发需要自己去定义较为复杂的表达式。

目录
相关文章
|
5月前
|
JavaScript 前端开发 API
javascript的惰性函数是什么?
本文介绍了JavaScript中的惰性函数概念及其应用。由于浏览器兼容性问题,一个API在不同浏览器中的表现可能不同,通常需要通过if判断来处理。但每次都执行if判断效率低下,因此引入了惰性函数。惰性函数确保if分支只执行一次,后续直接调用支持的代码分支,提升性能。文中提供了两种实现方案:一是首次调用时重定义函数;二是声明时即指定适当函数。最后分析了惰性函数的优缺点,并总结其核心思想为“一次性搞定,避免重复工作”。
|
JavaScript
vue组件
vue组件
144 1
|
Rust 安全 JavaScript
新手必看!Rust 初学者如何编写 Gear 智能合约(1)
本文将主要说明如何使用 Rust 在 Gear 区块链网络上创建一个简单的去中心化应用程序。
445 0
新手必看!Rust 初学者如何编写 Gear 智能合约(1)
|
存储 弹性计算 固态存储
开通阿里云 ECS 服务器|学习笔记
快速学习 开通阿里云 ECS 服务器
175 0
|
数据挖掘 开发者 索引
DataFrame 索引设置|学习笔记
快速学习 DataFrame 索引设置
899 0