首页 > 其他分享 >行为型设计模式之解释器模式

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

时间:2022-10-24 12:00:32浏览次数:53  
标签:解释器 终结符 模式 interpret IExpression 设计模式 public 表达式

解释器模式

解释器模式属于行为型模式。它是指给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。是一种按照规定的语法(文法)进行解析的模式

编译器可以将源码编译解释为机器码,让CPU能进行识别并运行。解释器模式的作用与编译器一样,都是将一些固定的文法(即语法)进行解释,构建出一个解释句子的解释器。

简单理解,解释器是一个简单语法分析工具,它可以识别句子语义,分离终结符号和非终结符号,提取出需要的信息,让我们能针对不同的信息做出相应的处理。其核心思想是识别文法,构建解释。

简而言之,解释器模式就是对于一些固定文法构建一个解释句子的解释器。

应用场景

适用场景:

1.一些重复出现的问题可以用一种简单的语言来进行表达;

2.一个简单语法需要解释的场景。

主要角色

解释器模式主要包含四种角色:

1.抽象表达式(Expression)

负责定义一个解释方法interpret,交由具体子类进行具体解释

2.终结符表达式(TerminalExpression)

实现文法中与终结符有关的解释操作。文法中的每一个终结符都有一个具体终结表达式与之相对应

如公式R=R1+R2,R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式

通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符(R1,R2)

3.非终结符表达式(NonterminalExpression)

实现文法中与非终结符有关的解释操作。

文法中的每条规则都对应于一个非终结符表达式。

非终结符表达式一般是文法中的运算符或者其他关键字,如公式R=R1+R2中,“+"就是非终结符,解析“+”的解释器就是一个非终结符表达式。

非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式

4.上下文环境类(Context)

包含解释器之外的全局信息。它的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,给R1赋值100,给R2赋值200,这些信息需要存放到环境中。

优缺点

优点:

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

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

缺点

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

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

基本使用

使用解释器模式解析数学表达式

创建抽象表达式

创建一个抽象表达式接口,定义一个表达式解释方法,由具体子类进行具体解释

public interface IExpression {
    /**
     *  对表达式进行解释
     */
    Object interpret();
}

创建终结符表达式

public  abstract class TerminalExpression implements IExpression {

    protected IExpression a;
    
    protected IExpression b;

    public TerminalExpression(IExpression a, IExpression b) {
        this.a = a;
        this.b = b;
    }
}

创建非终结符表达式

public class AddNonterminalExpression extends TerminalExpression {

    public AddNonterminalExpression(IExpression a, IExpression b) {
        super(a, b);
    }

    public int interpret() {
        return this.a.interpret()+this.b.interpret();
    }
}
public class SubNonterminalExpression extends TerminalExpression {

    public SubNonterminalExpression(IExpression a, IExpression b) {
        super(a, b);
    }

    public int interpret() {
        return this.a.interpret()-this.b.interpret();
    }
}
public class NumNonterminalExpression implements IExpression {
    private int value;

    public NumNonterminalExpression(int value) {
        this.value = value;
    }


    public int interpret() {
        return this.value;
    }
}

创建上下文环境类

public class CalculatorContext {
    private Stack<IExpression> stack = new Stack<IExpression>();

    public CalculatorContext(String expression) {
        this.parse(expression);
    }

    /**
     * 解析表达式
     *
     * @param expression 表达式
     */
    private void parse(String expression) {
        String[] elements = expression.split(" ");
        IExpression aExpr, bExpr;

        for (int i = 0; i < elements.length; i++) {
            String operator = elements[i];
            if (CalculatorContext.isOperator(operator)) {
                aExpr = this.stack.pop();
                System.out.println("出栈: " + aExpr.interpret());
                bExpr = new NumNonterminalExpression(Integer.valueOf(elements[++i]));
                TerminalExpression res = CalculatorContext.util(aExpr, bExpr, operator);
                this.stack.push(res);
                System.out.println("计算: " + aExpr.interpret() + operator + bExpr.interpret());
                System.out.println("计算结果: " + res.interpret() + " 入栈");
            } else {
                NumNonterminalExpression numNonterminalExpression = new NumNonterminalExpression(Integer.valueOf(elements[i]));
                this.stack.push(numNonterminalExpression);
                System.out.println("入栈: " + numNonterminalExpression.interpret());
            }
        }
    }

    /**
     * 计算结果
     *
     * @return
     */
    public int calculate() {
        int interpret = this.stack.pop().interpret();
        System.out.println("计算结果: " + interpret + "出栈");
        return interpret;
    }

    /**
     * 计算结果
     */
    public static TerminalExpression util(IExpression a, IExpression b, String symbol) {
        if (symbol.equals("+")) {
            return new AddNonterminalExpression(a, b);
        } else if (symbol.equals("-")) {
            return new SubNonterminalExpression(a, b);
        } else {
            return null;
        }
    }

    public static boolean isOperator(String symbol) {
        return (symbol.equals("+") || symbol.equals("-"));
    }
}

客户端执行

    public static void main(String[] args) {
        // 创建上下文对象进行解释
        CalculatorContext calculatorContext = new CalculatorContext("10 + 20");
        // 获取执行结果
        System.out.println("calculatorContext.calculate() = " + calculatorContext.calculate());

        CalculatorContext calculatorContext2 = new CalculatorContext("10 + 20 - 15");
        System.out.println("calculatorContext.calculate() = " + calculatorContext2.calculate());
    }
入栈: 10
出栈: 10
计算: 10+20
计算结果: 30 入栈
计算结果: 30出栈
calculatorContext.calculate() = 30
入栈: 10
出栈: 10
计算: 10+20
计算结果: 30 入栈
出栈: 30
计算: 30-15
计算结果: 15 入栈
计算结果: 15出栈
calculatorContext.calculate() = 15

标签:解释器,终结符,模式,interpret,IExpression,设计模式,public,表达式
From: https://blog.51cto.com/chencoding/5788979

相关文章

  • 设计模式之原型模式
    概述在使用原型模式时,需要首先创建一个原型对象,再通过复制这个原型对象来创建更多同类型的对象。其定义如下:使用原型实例指定创建对象的种类,并且通过克隆这些原型创建新的......
  • 浅谈PHP设计模式的工厂模式
    简介工厂模式属于创建型模式,可以分为三种:简单工厂、工厂模式、抽象工厂。通俗讲就是用于如何优雅的创建对象而设计。当开发者不知道建什么对象,或者创建方式过于复杂的时......
  • 共体经济的无盈利运行模式
    我们通常认为:生产与经营就是为了盈利,盈利就是赚取生产成本价格与销售价格之间的差价,不过,要说农民春天撒下种子,秋天收获粮食,这是在盈利,那就成笑话了,可见,盈利和创造劳动价值......
  • 设计模式 - 桥接模式
    目录实例数据转换工具桥接模式概念角色定义典型代码具体实现总结源码实例数据转换工具Sunny软件公司欲开发一个数据转换工具,可以将数据库中的数据转换成多种文件格式,例......
  • 装饰模式
    用装饰模式模拟手机功能的升级过程:简单的手机(SimplePhone)在接收来电时,会发出声音提醒主人;而JarPhone除了声音还能振动;更高级的手机(ComplexPhone)除了声音、振动外,还有灯......
  • 外观模式
    在计算机主机(Mainframe)中,只需要按下主机的开机按钮(on()),即可调用其他硬件设备和软件的启动方法,如内存(Memory)的自检(check())、CPU的运行(run())、硬盘(HardDisk)的读......
  • 享元模式
    设计一个围棋软件,在系统中只存在一个白棋对象和一个黑棋对象,但是它们可以在棋盘的不同位置显示多次。   ......
  • 《敏捷软件开发原则、模式与实践》(美)Robert C.Martin著 读书笔记(第一部分 敏捷开发 第
    关键词:《敏捷软件开发原则、模式与实践》,(美)RobertC.Martin,读书笔记,极限编程第二章极限编程概述极限编程(XP)实践1)客户作为团队成员  最好的情况是——客户和开......
  • 云计算的3种服务模式
    1.云基础设施即服务(IaaS):出租处理能力、存储空间、网络容量等基本计算资源。只提供基础的底层资源,用户需要自己安装操作系统、中间件、运行环境、数据、应用程序等。2.云平台......
  • 《敏捷软件开发原则、模式与实践》(美)Robert C.Martin著 读书笔记(第一部分 敏捷开发)
    关键词:《敏捷软件开发》原则、模式与实践》,(美)RobertC.Martin著,读书笔记,敏捷开发,敏捷实践 第一章敏捷实践敏捷联盟。       敏捷宣言:个体和交互......