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

1.解释器模式定义

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

1.1 解释器模式的优缺点

优点

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

缺点

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

1.2 解释器模式使用场景

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

2.解释器 模式原理

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

3.解释器模式的实现

【实例】

以加减乘除运算为例

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

【代码】

表达式接口

java 复制代码
public interface Expression {

    long interpret();
}

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

java 复制代码
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;
    }
}

非终结符表达式类

java 复制代码
/**
 * 加法运算
 **/
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();
    }
}

客户端

java 复制代码
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);
    }
}
相关推荐
Adellle2 小时前
设计模式指南 (Java 版) ㊁
java·开发语言·设计模式
是2的10次方啊3 小时前
设计模式与生活⑱:工资还没焐热,账单已经凑成一摞
设计模式
百思不得小李15 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
爱你真是太好了18 小时前
上下文组成以及如何压缩
设计模式
freejackman1 天前
【工程化】从“单兵作战”到“多引擎架构”:基于门面模式的重构实战
大数据·数据库·hive·sql·测试工具·设计模式·架构
Java成神之路-1 天前
从 if-else 到优雅解耦:策略 / 适配器 / 组合模式全流程实战
设计模式
是2的10次方啊1 天前
设计模式与生活⑰:空腹体检,单子领着人走
设计模式
是2的10次方啊2 天前
设计模式与生活⑯:天冷了,出门这身得一层层配
设计模式
心若自由何处是束缚3 天前
适配器模式:从原理到实战的完整指南
设计模式·适配器模式
是2的10次方啊3 天前
设计模式与生活⑮:看到哪儿了,得有个地方替你记着
设计模式