设计模式----解释器模式

一、简介

        解释器模式使用频率并不高,通常用来构建一个简单语言的语法解释器,它只在一些非常特定的领域被用到,比如编译器、规则引擎、正则表达式、sql解析等。

        解释器模式是行为型设计模式之一,它的原始定义为:用于定义语言语法规则表示,并提供解释器来处理句子中的语法。

        我们通过一个例子来解释下解释器模式,假设我们设计一个软件来进行加减计算,我们第一想法就是使用工具类,提供对应的加法和减法的工具方法。

public int add(int a,int b){
return a+b;
}

public int add(int a,int b,int c){
return a+b+c;
}
......

上面的形式比较单一、有限如果形式变化非常多,这就不符合要求,因为加法和减法运算,两个运算符数组可以有无限种合作方式,比如1+3+2+1-5....

        解释器模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。

二、结构

        解释器模式由以下几种角色组成:

        ①抽象表达式角色:定义解释器的接口,约定解释器的操作,主要包含解释方法interoret

        ②终结符表达式角色:用来实现文发中与终结符相关的操作,文法中的每一个终结符都有一个具体的终结符表达式与之对应

        ③非终结符表达式:用来实现文法中与非终结符相关的操作,文法中每条规则都对应一个非终结符表达式

        ④上下文类:通常包含各个解释器需要的数据或者是公共的功能,一般用来传递所有解释器共享的数据。

三、实现

        我们定义一个进行加减乘除计算的语言,语法规则如下:

        ①运算符只包含加减乘除,并且没有优先级概念

        ②表达式中,先写数字后写运算符,空格隔开

// 表达式接口
public interface Expression {
    int interpret();
}

// 加法解释器
public class AddExpression implements Expression {
    private Expression left;
    private Expression right;
    
    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret() {
        return left.interpret() + right.interpret();
    }
}

// 减法解释器
public class SubtractExpression implements Expression {
    private Expression left;
    private Expression right;
    
    public SubtractExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret() {
        return left.interpret() - right.interpret();
    }
}

// 乘法解释器
public class MultiplyExpression implements Expression {
    private Expression left;
    private Expression right;
    
    public MultiplyExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret() {
        return left.interpret() * right.interpret();
    }
}

// 除法解释器
public class DivideExpression implements Expression {
    private Expression left;
    private Expression right;
    
    public DivideExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret() {
        try {
            return left.interpret() / right.interpret();
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
            return -1;
        }
    }
}

// 数字解释器
public class NumberExpression implements Expression {
    private int number;
    
    public NumberExpression(int number) {
        this.number = number;
    }
    
    @Override
    public int interpret() {
        return number;
    }
}

现在我们可以使用这些类来解析四则运算表达式了。例如,对于表达式 “1 + 2 * 3 - 4 / 2”我们可以使用以下代码来解析该表达式:

Expression expression = new SubtractExpression(
                                new AddExpression(
                                    new NumberExpression(1),
                                    new MultiplyExpression(
                                        new NumberExpression(2),
                                        new NumberExpression(3)
                                    )
                                ),
                                new DivideExpression(
                                    new NumberExpression(4),
                                    new NumberExpression(2)
                                )
                            );
int result = expression.interpret();
System.out.println("计算结果为:" + result);

四、总结

优点

①易于改变可扩展文法,因为在解释器模式中实用类来表示语言的文法规则的,因此可以通过继承等机制改变或扩展文法,每一个文法规则都可以表示为一个类,因此我们可以快速的实现一个迷你的语言

②实现文法比较容易,在抽像语法术中每一个表达式节点的实现方式都是相似的,这些代码不特别复杂

③增加新的解释表达式比较方便,如果用户增加新的解释表达式,只需要对应增加一个新的表达式类就可以,原有的表达式不需修改,符合开闭原则

缺点

①对于复杂文法难以维护,在解释器中,一条规则至少要定义一个类,因此一个语言中有太多的文法规则,那么就会使类的个数急剧增加,导致系统的维护难以管理。

②执行效率低,在解释器模式中,大量的使用循环和递归调用,所以复杂的句子执行起来比较繁琐

使用场景

①当语言的文法比较简单时,并且执行的效率不是关键问题的时候

②当问题重复出现,且可以用一种简单的语言来表达

③当一个语言要解释执行,并且语言中的句子可以表示为一个抽象的语法树的时候。

相关推荐

  1. 设计模式——解释模式

    2023-12-24 18:14:03       56 阅读
  2. 设计模式解释模式

    2023-12-24 18:14:03       37 阅读
  3. 设计模式解释模式

    2023-12-24 18:14:03       30 阅读
  4. 设计模式-解释模式

    2023-12-24 18:14:03       30 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-24 18:14:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-24 18:14:03       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-24 18:14:03       82 阅读
  4. Python语言-面向对象

    2023-12-24 18:14:03       91 阅读

热门阅读

  1. vue 项目 index.html 中使用环境变量

    2023-12-24 18:14:03       59 阅读
  2. 语音信号加密算法MATLAB仿真

    2023-12-24 18:14:03       71 阅读
  3. npm使用详解(好吧好吧是粗解)

    2023-12-24 18:14:03       63 阅读
  4. 机器学习之实验过程02

    2023-12-24 18:14:03       53 阅读
  5. Starknet 命令行工具之Starkli | 使用Starkli部署合约

    2023-12-24 18:14:03       52 阅读
  6. 前端八股文(js篇 )

    2023-12-24 18:14:03       56 阅读
  7. 自动编码器图像去噪 Python

    2023-12-24 18:14:03       51 阅读
  8. 文件包含

    2023-12-24 18:14:03       51 阅读
  9. (C)一些题15

    2023-12-24 18:14:03       48 阅读
  10. Sepolia 和 Holesky 测试网对比

    2023-12-24 18:14:03       66 阅读
  11. LeetCode,第377场周赛,个人题解

    2023-12-24 18:14:03       50 阅读
  12. django框架、断言、请求与响应

    2023-12-24 18:14:03       60 阅读