《设计模式入门》 24.解释器模式

解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

解释器模式一般分为五类:

  1. 抽象解释器(AbstractExpression):具体的解释任务由各个实现类完成。
  2. 终结符表达式(TerminalExpression):实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结表达式,但有多个实例,对应不同的终结符。
  3. 非终结符表达式(NonterminalExpression):文法中的每条规则对应于一个非终结表达式,非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式
  4. 上下文(Context): 上下文环境类,包含解释器之外的全局信息
  5. 客户类(Test): 客户端,解析表达式,构建抽象语法树,执行具体的解释操作等.

一般我们除了SQL的定义,在很多别的地方也会看到,比如定义一个新的公式来进行运算,定义符号对应操作等等。

=========================================================================

我们来模仿定义写一个加减函数:

        输入一个模型公式(加减四则运算),然后输入模型中的参数,运算出结果。

定义一个解释器接口:

package BehavioralPatterns.InterpreterPattern;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Expression.java
 * @Description 解释器接口
 * @createTime 2022年03月18日 16:11:00
 */
public interface Expression {
    /**
     * 解释器
     * @param context 上下文
     * @return 结果值
     */
    int interpreter(Context context);
}

定义上下文:

package BehavioralPatterns.InterpreterPattern;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName Context.java
 * @Description 上下文
 * @createTime 2022年03月18日 16:12:00
 */
public class Context {

    private Map<Expression, Integer> map = new HashMap<>();
    /**
     * 定义变量
     * @param s 传入变量
     * @param value 对应的integer
     */
    public void add(Expression s, Integer value){
        map.put(s, value);
    }

    /**
     * 将变量转换成数字
     * @param s 传入的变量
     * @return 对应的数字
     */
    public int changeToNumber(Expression s){
        return map.get(s);
    }

}

定义抽象非终结符表达式:

package BehavioralPatterns.InterpreterPattern;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName NonTerminalExpression.java
 * @Description 抽象非终结符表达式
 * @createTime 2022年03月18日 16:13:00
 */
public abstract class NonTerminalExpression implements Expression {
    Expression e1,e2;

    public NonTerminalExpression (Expression e1, Expression e2){
        this.e1 = e1;
        this.e2 = e2;
    }

}

减法表达式实现类:

package BehavioralPatterns.InterpreterPattern;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName MinusOperation.java
 * @Description 减法表达式实现类
 * @createTime 2022年03月18日 16:15:00
 */
public class MinusOperation extends NonTerminalExpression{
    public MinusOperation(Expression e1, Expression e2) {
        super(e1, e2);
    }

    /**
     * 返回相减的值
     * @param context 上下文
     * @return 相减之后的值
     */
    @Override
    public int interpreter(Context context) {
        System.out.println(e1.interpreter(context) +"-" + e2.interpreter(context));
        return e1.interpreter(context) - e2.interpreter(context);
    }
}

加法表达式实现类:

package BehavioralPatterns.InterpreterPattern;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName PlusOperation.java
 * @Description 加法表达式实现类
 * @createTime 2022年03月18日 16:25:00
 */
public class PlusOperation extends NonTerminalExpression{
    public PlusOperation(Expression e1, Expression e2) {
        super(e1, e2);
    }

    @Override
    public int interpreter(Context context) {
        System.out.println(e1.interpreter(context) +"+" + e2.interpreter(context));
        return e1.interpreter(context) + e2.interpreter(context);
    }
}

终结符表达式:

package BehavioralPatterns.InterpreterPattern;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName TerminalExpression.java
 * @Description 终结符表达式
 * @createTime 2022年03月18日 16:17:00
 */
public class TerminalExpression implements Expression{
    String var;
    public TerminalExpression (String var){
        this.var = var;
    }


    @Override
    public int interpreter(Context context) {
        return context.changeToNumber(this);
    }
}

测试一下:

package BehavioralPatterns.InterpreterPattern;

/**
 * @author Zeyu Wan
 * @version 1.0.0
 * @ClassName InterpreterTest.java
 * @Description 测试类
 * @createTime 2022年03月18日 16:21:00
 */
public class InterpreterTest {
    public static void main(String[] args) {
        Context context = new Context();
        TerminalExpression a = new TerminalExpression("a");
        TerminalExpression b = new TerminalExpression("b");
        TerminalExpression c = new TerminalExpression("c");

        context.add(a,1);
        context.add(b,2);
        context.add(c,3);
        System.out.println("="+new MinusOperation(new PlusOperation(a,b),c).interpreter(context));
    }
}

 

优点:

      解释器是一个简单语法分析工具,它最显著的优点就是扩展性,修改语法规则只要修改相应的非终结符表达式就可以了,若扩展语法,则只要增加非终结符类就可以了。

缺点:

  • 解释器模式会引起类膨胀

      每个语法都要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来了非常多的麻烦。

  • 解释器模式采用递归调用方法

      每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,必须一层一层地剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,它导致调试非常复杂。想想看,如果要排查一个语法错误,我们是不是要一个一个断点的调试下去,直到最小的语法单元。

  • 效率问题

      解释器模式由于使用了大量的循环和递归,效率是个不容忽视的问题,特别是用于解析复杂、冗长的语法时,效率是难以忍受的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PigeonEssence

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值