IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 解释器模式,女朋友给男朋友的一个机会! -> 正文阅读

[Java知识库]解释器模式,女朋友给男朋友的一个机会!

? **请注意!请注意!!!**今天讲给大家讲解非常“有用”的设计模式,解释器模式!!!

? 设计模式有三大种类,一种是创建型模式,一种是结构型模式,最后一种是行为性模式,那么解释器模式属于哪一种呢?带领大家一起来了解学习解释器模式!

? 本次介绍围绕着以下五点展开。什么是解释器模式?用来做什么?怎么做?有哪些优点?有哪些不足?

? 解释器模式顾名思义,就是用来定义解释

? 给定一种特定语言,这个语言有特定的文法,解释器可以解释这个语言中的句子含义。即解释器提供一种语言,如java,同时它也提供一种手段去解析java语言写出来的代码

? 大家可能也会想到这就是类似编译原理,一个算术表达式要经过词法分析,语法分析,构建语法树啥的;还有正则表达式;SQL解析,编译器等等,其实都是解析式模式的一种实现

? 那怎么做?一个是说要有像编译原理中的终结符非终结符,构建一颗语法树。同时需要有一个环境类,来管理输入和输出

? 这里我们举一个例子,输入一个表达式a+b-c+d-e,同时给这5个变量赋值,计算出它的值。那么使用解释器模式要如何实现?

? 我们为解释器定义一个抽象解释类Expression,所有的流转通过interpreter方法实现。

? 上下文管理输入输出使用一个HashMap去实现。

? 定义符号解释类SymbolExpression,加法解释类AddExpreesion,减法解释类SubExpression

类图:

在这里插入图片描述

具体代码实现:

public abstract class Expression {

    // map中携带了表达式中的变量名(key) 和 对应的值(value)
    public abstract int interpreter(Map<String, Integer> var);

}

public class VarExpression extends Expression {

    // 表达式中对应的变量名
    String key;

    public VarExpression(String var) {
        this.key = var;
    }

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

public class SymbolExpression extends Expression {

    // +或-符号 左右两边的表达式
    Expression var1;
    Expression var2;

    public SymbolExpression(Expression var1, Expression var2) {
        this.var1 = var1;
        this.var2 = var2;
    }

    @Override
    public int interpreter(Map<String, Integer> var) {
        // 实现抽象方法
        // 该类不需要用到该方法 默认返回0
        return 0;
    }
}

public class AddExpression extends SymbolExpression {

    public AddExpression(Expression var1, Expression var2) {
        super(var1, var2);
    }

    @Override
    public int interpreter(Map<String, Integer> var) {
        return var1.interpreter(var) + var2.interpreter(var);
    }
}

public class SubExpression extends SymbolExpression {

    public SubExpression(Expression var1, Expression var2) {
        super(var1, var2);
    }

    @Override
    public int interpreter(Map<String, Integer> var) {
        return var1.interpreter(var) - var2.interpreter(var);
    }

}

public class Calculator {

    // 表达式
    private Expression expression;

    // 解析出表达式
    public Calculator(String expStr) {
        Stack<Expression> stack = new Stack<>();
        Expression left, right = null;
        char[] expStrCharArray = expStr.toCharArray();

        for(int i = 0; i < expStrCharArray.length; i++) {
            switch (expStrCharArray[i]) {
                case '+':// 加法运算 获取左边表达式 右边数值
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(expStrCharArray[++i]));
                    stack.push(new AddExpression(left, right));
                    break;
                case '-':// 减法运算 获取左边表达式 右边数值
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(expStrCharArray[++i]));
                    stack.push(new SubExpression(left, right));
                    break;
                default:// 表达式中的变量
                    stack.push(new VarExpression(String.valueOf(expStrCharArray[i])));
                    break;
            }
        }
        // 最后会获得被Expression包装起来的一个表达式
        this.expression = stack.pop();
    }

    // 计算结果
    public int run(Map<String, Integer> var) {
        return this.expression.interpreter(var);
    }
}

public class Client {

    public static void main(String[] args) throws IOException {
        String expStr = getExpStr();
        Map<String, Integer> var = getValue(expStr);
        Calculator calculator = new Calculator(expStr);
        System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
    }

    //获得表达式
    public static String getExpStr() {
        return "a+b-c+d-e";
    }

    //获得值映射
    public static HashMap<String, Integer> getValue(String expStr) throws IOException {
        HashMap<String, Integer> map = new HashMap<>();

        for(char ch : expStr.toCharArray()) {
            if(ch != '+' && ch != '-' ) {
                if(! map.containsKey(String.valueOf(ch))) {
                    System.out.print("请输入" + String.valueOf(ch) + "的值:");
                    String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
                    map.put(String.valueOf(ch), Integer.valueOf(in));
                }
            }
        }

        return map;
    }

}
/*
请输入a的值:1
请输入b的值:3
请输入c的值:5
请输入d的值:7
请输入e的值:9
运算结果:a+b-c+d-e=-3
*/

? 或许看代码会有点云里雾里,希望大家能手动敲一遍,或许会对整个过程有更进一步的理解,在编码的同时不断思考,提升自我

? 很容易发现解释器模式是属于行为性模式的一种,这种模式更关注对象之间的通信。

? 解释器模式优点,结构清晰,可拓展性好。但也有缺点,一般用在比较底层场景,平常敲代码可使用的场景比较少,并且解释器模式采用的是递归的方式,当语言比较长,性能不高;同时如果文法比较复杂,也需要更多的相应解释类。

? 好了,希望本篇文章对你有所帮助!

在这里插入图片描述

愿每个人都能带着怀疑的态度去阅读文章并探究其中原理。

道阻且长,往事作序,来日为章。

期待我们下一次相遇!

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-13 11:19:57  更:2021-10-13 11:20:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 21:13:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码