设计模式——解释器模式

这篇具有很好参考价值的文章主要介绍了设计模式——解释器模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

更多内容,前往IT-BLOG

在软件开发中,会遇到有些问题多次重复出现,而且有一定的相似性和规律性。如果将它们归纳成一种简单的表达式(例如:正则表达式等),那么这些问题实例将是该表达式的一些句子,这样就可以用 “编译原理” 中的解释器模式来实现。

一、解释器模式基本介绍

【1】解释器模式(Interpreter Pattern): 是指给定一个语言(表达式),定义它的文法的一种表示。并定义一个解释器,使用该解释器来解释语言中的句子(表达式)。
【2】在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树。这里的词法分析器和语法分析器都可以看做是解释器。
【3】解释器模式是一种类行为型模式,其主要优点如下: ①、扩展性好,由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。②、容易实现,在语法树中的每个表达式节点类都是相似的,所以实现其文法较为容易。
【4】解释器模式的主要缺点如下: ①、执行效率较低。解释器模式中通常使用大量的循环和递归调用,当要解释的句子较复杂时,其运行速度很慢,且代码的调试过程也比较麻烦。②、会引起类膨胀。解释器模式中的每条规则至少需要定义一个类,当包含的文法规则很多时,类的个数将急剧增加,导致系统难以管理与维护。③、可应用的场景比较少。在软件开发中,需要定义语言文法的应用实例非常少,所以这种模式很少被使用到。
【5】应用场景: ①、应用可以将一个需要解释执行的语言中的句子表示为一个抽象语法树 。②、一些重复出现的问题可以用一种简单的语言来表达。③、一个简单语法需要解释的场景。
【6】这样的例子还有,比如编译器、运算表达式计算、正则表达式、机器人等。

二、解释器模式的结构与类图

解释器模式包含以下主要角色:
【1】抽象表达式(Abstract Expression)角色: 定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
【2】终结符表达式(Terminal Expression)角色: 是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
【3】非终结符表达式(Nonterminal Expression)角色: 也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
【4】环境(Context)角色: 通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
【5】客户端(Client): 主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。

设计模式——解释器模式,设计模式,设计模式,解释器模式,java,后端,面试,性能优化,架构

三、解释器模式案例分析

【1】抽象表达式: 抽象类表达式,通过 HashMap 键值对, 可以获取到变量的值。

/**
 * 抽象类表达式,通过HashMap 键值对, 可以获取到变量的值
 */
public abstract class Expression {
    // a + b - c
    // 解释公式和数值, key 就是公式(表达式) 参数[a,b,c], value就是就是具体值
    // HashMap {a=10, b=20}
    public abstract int interpreter(HashMap<String, Integer> var);
}

【2】终结符表达式:

public class Calculator {
 
    // 定义表达式
    private Expression expression;
 
    // 构造函数传参,并解析
    public Calculator(String expStr) { // expStr = a+b
        // 安排运算先后顺序
        Stack<Expression> stack = new Stack<>();
        // 表达式拆分成字符数组
        char[] charArray = expStr.toCharArray();// [a, +, b]
 
        Expression left = null;
        Expression 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 就创建要给 VarExpression 对象,并push到 stack
                stack.push(new VarExpression(String.valueOf(charArray[i])));
                break;
            }
        }
        //当遍历完整个 charArray 数组后,stack 就得到最后Expression
        this.expression = stack.pop();
    }
 
    public int run(HashMap<String, Integer> var) {
        //最后将表达式a+b和 var = {a=10,b=20}
        //然后传递给expression的interpreter进行解释执行
        return this.expression.interpreter(var);
    }
}

【3】非终结符表达式(抽象): 抽象运算符号解析器 这里,每个运算符号,都只和自己左右两个数字有关系。

/**
 * 抽象运算符号解析器 这里,每个运算符号,都只和自己左右两个数字有关系,
 * 但左右两个数字有可能也是一个解析的结果,无论何种类型,都是Expression类的实现类
 *
 * @author Administrator
 *
 */
public class SymbolExpression extends Expression {
 
    protected Expression left;
    protected Expression right;
 
    public SymbolExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
 
    //因为 SymbolExpression 是让其子类来实现,因此 interpreter 是一个默认实现
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        // TODO Auto-generated method stub
        return 0;
    }
}

【4】非终结符表达式(实现一):

// 加法解释器
public class AddExpression extends SymbolExpression  {
 
    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }
 
    //处理相加
    //var 仍然是 {a=10,b=20}..
    //一会我们debug 源码,就ok
    public int interpreter(HashMap<String, Integer> var) {
        //super.left.interpreter(var) : 返回 left 表达式对应的值 a = 10
        //super.right.interpreter(var): 返回right 表达式对应值 b = 20
        return super.left.interpreter(var) + super.right.interpreter(var);
    }
}

【5】非终结符表达式(实现二):

public class SubExpression extends SymbolExpression {
 
    public SubExpression(Expression left, Expression right) {
        super(left, right);
    }
 
    //求出left 和 right 表达式相减后的结果
    public int interpreter(HashMap<String, Integer> var) {
        return super.left.interpreter(var) - super.right.interpreter(var);
    }
}

【6】客户端:文章来源地址https://www.toymoban.com/news/detail-780479.html

public class ClientTest {
 
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        String expStr = getExpStr(); // a+b
        HashMap<String, Integer> var = getValue(expStr);// var {a=10, b=20}
        Calculator calculator = new Calculator(expStr);
        System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
    }
 
    // 获得表达式
    public static String getExpStr() throws IOException {
        System.out.print("请输入表达式:");
        return (new BufferedReader(new InputStreamReader(System.in))).readLine();
    }
 
    // 获得值映射
    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;
    }
}

到了这里,关于设计模式——解释器模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式:解释器模式

    解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言的文法,并且定义了该语言中各个元素的解释器。通过使用解释器,可以解析和执行特定的语言表达式。 解释器模式的核心思想是将一个语言的文法表示为一个类的层次结构,并使用该类的实例来表示

    2024年02月07日
    浏览(33)
  • 设计模式——解释器模式

    更多内容,前往IT-BLOG 在软件开发中,会遇到有些问题多次重复出现,而且有一定的相似性和规律性。如果将它们归纳成一种简单的表达式(例如:正则表达式等),那么这些问题实例将是该表达式的一些句子,这样就可以用 “编译原理” 中的解释器模式来实现。 【1】解释

    2024年02月03日
    浏览(26)
  • 【解释器设计模式详解】C/Java/Go/JS/TS/Python不同语言实现

    解释器模式(Interpreter Pattern)是一种行为型设计模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式常被用在 SQL 解析、符号处理引擎等。 解释器模式常用于对简单语言的编译或分析实例中,为了掌握好它的结构与实现,必须先了解编译原理中的

    2023年04月12日
    浏览(29)
  • 设计模式详解-解释器模式

    类型:行为型模式 实现原理:实现了一个表达式接口,该接口使用标识来解释语言中的句子 作用:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器来解释。 主要解决:一些重复的固定文法分别创建解释器会很麻烦 何时使用:某一种特定类型的问题发生的

    2024年02月12日
    浏览(38)
  • 解释器设计模式

    解释器设计模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言的文法,并建立一个解释器来解释该语言中的句子。这种模式通常用于需要解释或执行一种特定类型的语言的场景,例如编程语言的编译器或解释器、规则引擎系统等。 关键组成部分 抽象表达式(

    2024年02月21日
    浏览(38)
  • 设计模式(行为型模式)解释器模式

       解释器模式(Interpreter Pattern) 是一种行为设计模式,用于解释特定语言或处理特定问题领域的语法或表达式。它定义了一种语言的语法表示,并使用该表示来解释语言中的句子。通常用于构建解析器、编译器和规则评估引擎等场景。 在解释器模式中,有以下关键角色:

    2024年02月20日
    浏览(33)
  • js设计模式:解释器模式

    对文本进行解释和编译的时候,就会用到解释器模式 比如你写了一段js代码,js引擎就会去解释并执行这段代码 webpack中的各种loader就是用来解释各种文件类型的,并将其解释为js可识别的代码

    2024年02月22日
    浏览(31)
  • 设计模式之解释器模式(下)

    3)Context的作用 1.概述 在解释器模式中,环境类Context用于存储解释器之外的一些全局信息,它通常作为参数被传递到所有表达式的解释方法interpret()中,可以在Context对象中存储和访问表达式解释器的状态,向表达式解释器提供一些全局的、公共的数据,此外还可以在Context中

    2024年04月12日
    浏览(30)
  • 设计模式之解释器模式笔记

    记录下学习设计模式-解释器模式的写法。JDK使用版本为1.8版本。 意图 :定义一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 结构 : 其中: AbstractExpression 声明一个程序的解释操作,这个接口为抽象语法树中所有的结点所

    2024年02月11日
    浏览(34)
  • 设计模式(十五)解释器

    定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。解释器模式是一种行为型模式。 解释器模式是一种使用频率相对较低但学习难度较大的设计模式,它主要用于描述如何使用面向对象语言构成一个简单的语言

    2024年02月05日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包