当前位置: 首页 > article >正文

设计模式-行为型模式-解释器模式

1.解释器模式定义

        用于定义语言的语法规则表示,并提供解释器来处理句子中的语法;

1.1 解释器模式的优缺点

优点

  • 易于修改、扩展,因为在解释器模式中使用类来表示语言的文法规则,因此就可以通过继承等机制改变或者扩展文法,每个文法规则都可以表示为一个类,因此我们可以快速地实现一个迷你的语言;
  • 实现文法比较容易,在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂;
  • 增加新的解释表达式比较方便,如果用户需要增加新的解释表达式,只需对应增加一个新的表达式就可以了,原有表达式类不需要修改,符合开闭原则;

缺点

  • 对于复杂文法难以维护,在解释其中一条规则至少要定义一个类,因此一个语言中如果有太多的文法规则,就会使类的个数急剧增加,当值系统的维护难以管理;
  • 执行效率低,在解释器模式中大量的使用了循环和递归调用,所有复杂的句子执行起来,整个过程非常繁琐;

1.2 解释器模式使用场景

  • 当语言的文法比较简单,并且执行效率不是关键问题.
  • 当问题重复出现,且可以用一种简单的语言来进行表达
  • 当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象的语法树的时候 

 2.解释器模式原理

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

3.解释器模式的实现

【实例】

        以加减乘除运算为例

  • 运算符只包含加、减、乘、除,并且没有优先级的概念;
  • 表达式中,先书写数字,后书写运算符,空格隔开;

【代码】

        表达式接口

public interface Expression {

    long interpret();
}

        数字表达式-终结符表达式类

public class NumExpression implements Expression {

    private long number;

    public NumExpression(long number) {
        this.number = number;
    }

    public NumExpression(String number) {
        this.number = Long.parseLong(number);
    }

    @Override
    public long interpret() {
        return this.number;
    }
}

        非终结符表达式类

/**
 * 加法运算
 **/
public class PluExpression implements Expression{

    private Expression exp1;
    private Expression exp2;

    public PluExpression(Expression exp1, Expression exp2) {
        this.exp1 = exp1;
        this.exp2 = exp2;
    }

    @Override
    public long interpret() {
        return exp1.interpret() + exp2.interpret();
    }
}

/**
 * 减法运算
 **/
public class SubExpression implements Expression {

    private Expression exp1;
    private Expression exp2;

    public SubExpression(Expression exp1, Expression exp2) {
        this.exp1 = exp1;
        this.exp2 = exp2;
    }

    @Override
    public long interpret() {
        return exp1.interpret() - exp2.interpret();
    }
}

/**
 * 乘法运算
 **/
public class MulExpression implements Expression {

    private Expression exp1;
    private Expression exp2;

    public MulExpression(Expression exp1, Expression exp2) {
        this.exp1 = exp1;
        this.exp2 = exp2;
    }

    @Override
    public long interpret() {
        return exp1.interpret() * exp2.interpret();
    }
}

/**
 * 除法
 **/
public class DivExpression implements Expression {

    private Expression exp1;
    private Expression exp2;

    public DivExpression(Expression exp1, Expression exp2) {
        this.exp1 = exp1;
        this.exp2 = exp2;
    }

    @Override
    public long interpret() {
        return exp1.interpret() / exp2.interpret();
    }
}

        客户端

public class Client {

    public static void main(String[] args) {

        ExpressionInterpreter e = new ExpressionInterpreter();
        long result = e.interpret("6 2 3 2 4 / - + *");
        System.out.println(result);
    }
}

http://www.kler.cn/a/312390.html

相关文章:

  • pySpark乱码
  • Flink_DataStreamAPI_输出算子Sink
  • 物理设备命名规则(Linux网络服务器 15)
  • Gurobi学术版+Anaconda安装步骤
  • 操作系统离散存储练习题
  • 如何提高自动驾驶中惯性和卫星组合导航pbox的精度?
  • Python 解析 Charles JSON Session File (.chlsj)
  • 攻防世界--->gametime
  • 数据结构-2.7.单链表的查找与长度计算
  • linux-系统管理与监控-磁盘管理
  • mysql学习教程,从入门到精通,SQL DISTINCT 子句 (16)
  • DeDeCMS靶场漏洞复现
  • 前端vue-父传子
  • 2024年亲测好用的四大在线翻译工具大盘点!
  • keras和tensorflow可用的一组版本
  • 【百日算法计划】:每日一题,见证成长(013)
  • MySQL练手题--获得最近第二次的活动(困难)
  • 【JVM】符号引用 和 直接引用
  • 中国计算机学会(CCF)推荐中文科技期刊目录(2019年)
  • nacos报Client not connected, current status:STARTING
  • Stable Diffusion绘画 | ControlNet应用-IP-Adapter:堪比 Midjourney 垫图
  • Ubuntu在CMakeLists.txt中指定OpenCV版本的参考方法
  • 【QT基础】创建项目项目代码解释
  • Python和Java的自动化测试技术研究及应用探索
  • Linux Vim编辑器常用命令
  • 【源码+文档+调试讲解】健身房管理平台小程序