解释器模式(二十三)

news2024/10/7 4:26:23

相信自己,请一定要相信自己

上一章简单介绍了 备忘录模式(二十二), 如果没有看过, 请观看上一章

一. 解释器模式

引用 菜鸟教程里面 解释器模式介绍: https://www.runoob.com/design-pattern/interpreter-pattern.html

解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。

这种模式实现了一个表达式接口,该接口解释一个特定的上下文。

这种模式被用在 SQL 解析、符号处理引擎等。

一.一 介绍

意图: 给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

主要解决: 对于一些固定文法构建一个解释句子的解释器。

何时使用: 如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。
这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

如何解决: 构建语法树,定义终结符与非终结符。

关键代码: 构建环境类,包含解释器之外的一些全局信息,一般是 HashMap。

应用实例: 编译器、运算表达式计算。

优点:
1、可扩展性比较好,灵活。
2、增加了新的解释表达式的方式。
3、易于实现简单文法。

缺点:
1、可利用场景比较少。
2、对于复杂的文法比较难维护。
3、解释器模式会引起类膨胀。
4、解释器模式采用递归调用方法。

使用场景:
1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
2、一些重复出现的问题可以用一种简单的语言来进行表达。
3、一个简单语法需要解释的场景。

注意事项: 可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。


组成角色具体关系
抽象表达式(AbstractExpression)MathExpression抽象表达式, 声明一个抽象的解释操作,这个方法为抽象语法树中所有的节点所共享
终结符表达式(TerminalExpression)BaseMathExpression为终结符表达式, 实现与文法中的终结符相关的解释操作
非终结符表达式(NonTermialExpression)VarExpression非终结符表达式,为文法中的非终结符实现解释操作.
环境角色(Context)MathCalculator环境角色,含有解释器之外的全局信息

image-20230615194033150

二. 解释器模式实例

二. 一 抽象表达式 MathExpression

public abstract class MathExpression {
    /**
     处理表达式
     * @param paramMap
     */
    public abstract int interpreter (Map<String, Integer> paramMap);
}

二.二 非终结符表达式 VarExpression

public class VarExpression extends MathExpression {
    private String key;
    public VarExpression (String key) {
        this.key = key;
    }

    @Override
    public int interpreter(Map<String, Integer> paramMap) {
        return paramMap.get(key);
    }
}

二.三 终结符表达式 和其子类

二.三.一 终结符表达式 BaseMathExpression

public class BaseMathExpression extends MathExpression{

    private MathExpression left;
    private MathExpression right;

    public BaseMathExpression (MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpreter(Map<String, Integer> paramMap) {
        // 是个空方法,让子类进行重写.
        return 0;
    }

    public MathExpression getLeft() {
        return left;
    }

    public MathExpression getRight() {
        return right;
    }
}

二.三.二 终结符表达式子类

相加

public class AddExpression extends BaseMathExpression{

    public AddExpression(MathExpression left, MathExpression right) {
        super(left, right);
    }

    @Override
    public int interpreter(Map<String, Integer> paramMap) {
        return super.getLeft().interpreter(paramMap) + super.getRight().interpreter(paramMap);
    }
}

相减

public class SubExpression extends BaseMathExpression{

    public SubExpression(MathExpression left, MathExpression right) {
        super(left, right);
    }

    @Override
    public int interpreter(Map<String, Integer> paramMap) {
        return super.getLeft().interpreter(paramMap) - super.getRight().interpreter(paramMap);
    }
}

二.四 环境角色 MathCalculator

public class MathCalculator {

    private MathExpression mathExpression;

    /**
    构造方法传入一个表达式
     */
    public MathCalculator (String expStr) {
   // 安排运算先后顺序
        Stack<MathExpression> stack = new Stack<>();
        // 表达式拆分成字符数组
        // 进行拆分
        char[] charArray = expStr.toCharArray();
        MathExpression left = null;
        MathExpression right = null;
        //遍历我们的字符数组, 即遍历  [a, +, b]
        //针对不同的情况,做处理
        for (int i = 0; i < charArray.length; i++) {
            switch (charArray[i]) {
                case '+':{
                    left = stack.pop();// 从stack取出left => "a"
                    right = new VarExpression(String.valueOf(charArray[++i]));// 取出右表达式 "b"
                    stack.push(new AddExpression(left, right));// 然后根据得到left 和 right 构建 AddExpresson加入stack
                    break;
                }
                case '-':{
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    stack.push(new SubExpression(left, right));
                    break;
                }
                default:{
                    //如果是一个 Var 就创建要给 VarMathExpression 对象,并push到 stack
                    stack.push(new VarExpression(String.valueOf(charArray[i])));
                    break;
                }
            }
        }
        //当遍历完整个 charArray 数组后,stack 就得到最后MathExpression
        this.mathExpression = stack.pop();


    }
    /**
     对外提供的一个方法, 用于获取结果
     */
    public int exec (Map<String,Integer> paramMap) {
        return this.mathExpression.interpreter(paramMap);
    }
}

二.五 客户端调用

   @Test
    public void oneTest() {
        MathCalculator mathCalculator = new MathCalculator("a+b-c+d-e");

        // 定义参数
        Map<String,Integer> paramMap = new HashMap<>();
        paramMap.put("a",1);
        paramMap.put("b",2);
        paramMap.put("c",3);
        paramMap.put("d",4);
        paramMap.put("e",5);

        int result = mathCalculator.exec(paramMap);
        log.info("最后结果是:{}",result);

    }

INFO [main] (InterpreterTest.java:33) - 最后结果是:-1

三. JEP 处理数学表达式

三.一 引入jep 依赖

<dependency>
            <groupId>jep</groupId>
            <artifactId>jep</artifactId>
            <version>2.24</version>
        </dependency>

三.二 JEP使用测试

@Test
    public void twoTest() {
        JEP jep = new JEP();
        // 需要先添加变量, 再处理表达式。
        jep.addVariable("a",1);
        jep.addVariable("b",2);
        jep.addVariable("c",3);
        jep.addVariable("d",4);
        jep.addVariable("e",5);
        jep.parseExpression("a+b-c+d-e");
        // 进行获取结果
        log.info(">>> 最后结果: {}", jep.getValue());
    }

INFO [main] (InterpreterTest.java:48) - >>> 最后结果: -1.0

较复杂的公式可以使用 SpEL 处理。 SpEL 可以看老蝴蝶之前写的文章: SpringBoot SpEL表达式(五十二)


本章节的代码放置在 github 上:


https://github.com/yuejianli/DesignPattern/tree/develop/Interpreter


谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/652137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

科研热点|影响因子发布时间确定,AHCIESCI将首获IF~

根据科睿唯安&#xff08;Clarivate&#xff09;官方公众号消息&#xff0c;2023年度《期刊引证报告》&#xff08;Journal Citation Reports&#xff0c;简称JCR&#xff09;即将于今年6月底正式发布&#xff01; 本年度JCR将对Web of Science核心合集收录的所有期刊赋予期刊…

C语言指针讲解(适用于初学者)

本文参考视频: https://b23.tv/xLOG6SV,相当于学习笔记&#xff0c;这样概念混淆的时候也可以看看。 一.一级指针 以下图表示的意思是&#xff1a; a的地址为0XA0&#xff0c;定义一个指针p&#xff0c;指向a的地址&#xff0c;计算机也会给p一个内存空间&p:0XB0 图中&a…

【机器学习】十大算法之一 “KNN”

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

疑似有用户安装Win11六月更新之后,无法打开Chrome浏览器

近日有网友表示&#xff0c;在安装6月更新的KB5027231之后&#xff0c;无法打开Chrome浏览器了&#xff0c;并且在任务管理器中可以看到相关**ERP系统**进程&#xff0c;但是 Chrome浏览器无法显示。 据了解&#xff0c;微软在本月的补丁星期二活动中&#xff0c;面向Win11发布…

MySQL:多表查询(全面详解)

MySQL&#xff1a;多表查询 前言附录&#xff1a;常用的 SQL 标准有哪些一、一个案例引发的多表连接1、案例说明2、笛卡尔积&#xff08;或交叉连接&#xff09;的理解3、案例分析与问题解决 二、多表查询分类讲解1、等值连接 vs 非等值连接1.1 等值连接1.2 非等值连接 2、自连…

chatgpt赋能python:使用Python生成应用的SEO

使用Python生成应用的SEO 在当今数字化时代中&#xff0c;拥有一个优化良好的应用程序对于任何企业都是至关重要的。 SEO&#xff08;搜索引擎优化&#xff09;是一个崭新且不断发展的领域&#xff0c;它对于企业非常具有建设性。在本文中&#xff0c;我们将学习如何使用Pytho…

CADisplayLink前世今生

本文字数&#xff1a;19803字 预计阅读时间&#xff1a;50分钟 用最通俗的语言&#xff0c;描述最难懂的技术 前情描述 上周同事做code review的时候说到了CADisplayLink的一些变化&#xff0c;感触颇深&#xff0c;提到了接口的一些变动&#xff0c;现在就自己的一些理解加上网…

全志V3S嵌入式驱动开发(spi-nand驱动)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 nand flash相信大家并不陌生&#xff0c;现在很多的固态硬盘上面&#xff0c;其实有很多的nand flash。只不过根据存储单元&#xff0c;分成slc、m…

人机融合与因果关系

苏格兰哲学家大卫.休谟认为因果关系很难被认识&#xff0c;主要是因为他认为我们的认识是通过经验得来的&#xff0c;而经验只能告诉我们事件的先后顺序&#xff0c;而不能告诉我们事件之间的必然联系。他提出了“常见的联想”&#xff08;常见的经验&#xff09;和“原则的联想…

使用 MATLAB 进行气象激光雷达图像分析(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

状态模式(二十四)

相信自己&#xff0c;请一定要相信自己 上一章简单介绍了 解释器模式(二十三), 如果没有看过, 请观看上一章 一. 状态模式 引用 菜鸟教程里面 状态模式介绍: https://www.runoob.com/design-pattern/state-pattern.html 在状态模式&#xff08;State Pattern&#xff09;中&…

go常用特性(embed、插件化开发)、常用包(并发)

go常用特性及常用包 1 常用特性 1.1 go:build //go:build !windows //go:build是前缀指令&#xff0c;!windows是逻辑判断的条件。这个指令的作用是在Windows系统外&#xff0c;编译当前源文件。// build !windows // build是前缀指令&#xff0c;!windows是编译标记。这个指…

CSDN如何获得铁粉?

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

springboot+vue的校园疫情防控系统(附数据库,源码)

&#x1f495;&#x1f495;作者&#xff1a;程序员徐师兄 个人简介&#xff1a;7 年大厂程序员经历&#xff0c;擅长Java、微信小程序、Python、Android等&#xff0c;大家有这一块的问题可以一起交流&#xff01; 各类成品java毕设 。javaweb&#xff0c;ssh&#xff0c;ssm&…

责任链模式(二十六)

相信自己&#xff0c;请一定要相信自己 上一章简单介绍了策略模式(二十五), 如果没有看过, 请观看上一章 一. 责任链模式 引用 菜鸟教程里面的责任链模式介绍: https://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html 顾名思义&#xff0c;责任链模式…

Science Advance||个体动态脑中鲁棒的大脑状态

文章目录 个体化动态方法&#xff08;INSCAPE 方法&#xff09;&#xff1a;&#xff08;A&#xff09;生成脑共同激活状态的组模板&#xff1a;&#xff08;B&#xff09;个体水平分析&#xff1a; 不同的大脑状态有特定的协同激活模式&#xff08;coactivation patterns&…

ai写作怎么搞?我来教你几招

在当今信息化时代&#xff0c;ai技术的发展已经进入到了一个全新的阶段&#xff0c;越来越多的人们开始运用ai技术进行写作。作为一种创新性的工具&#xff0c;ai写作已经成为了许多企业和个人写作必不可少的工具之一。但是&#xff0c;对于初学者来说&#xff0c;如何快速上手…

【网络技术】NAT是什么?它的工作原理是什么?

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、NAT是什么&#xff1f; 二、NAT的实现方式&#xff08;三种&#xff09; 1、静态转换&#xff08;Static Nat&#xff09; 2、动…

css line-height

项目中看到 line-height&#xff1a;1 所以来总结一下 line-height 属性。 line-height 定义 line-height 属性设置行间的距离&#xff08;行高&#xff09;。 line-height 不允许使用负值。 属性可能的值 值描述normal默认。设置合理的行间距。number设置数字&#xff0…

手机技巧:安卓微信 8.0.38 内测版本功能一览

2023年6月14号安卓版本的微信8.0.38又开始内测了&#xff0c;今天就赶紧下载体验一下&#xff0c;下面就来给大家一一介绍&#xff0c;本次安卓微信内测版本功能更新&#xff0c;感兴趣的朋友可以文末下载体验一下&#xff01; 首先看一下官方的更新内容&#xff1a; 本次更新…