2021年10月7日-设计模式之解释器模式

第二十一章:解释器模式

一、模式简介

1)编译原理中:一个算术表达式通过词法分析器形成词法单元,而后这些词法单元通过语法分析器构建语法分析树,最终形成一个抽象的语法分析树。词法分析器和语法分析器都可以看作是解释器

2)解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,使用这个解释器来解释语言中的表达式

3)应用场景:

  • 一些重复出现的问题可以用一种简单的语言来表达(正则表达式)
  • 一个简单语法需要解释的场景(运算表达式计算)
  • 一个需要解释执行的语言中的句子表示为一个抽象语法树(编译器、解释器、机器人)

基本类图:

在这里插入图片描述

  • Context:含有解释器之外的全局信息
  • AbstractExpression:抽象表达式,声明表达式的解释器行为
  • TerminalExpression:终结表达式,就是语法分析树上的叶子节点
  • NonTerminalExpression:非终结表达式,语法分析树上的非叶子节点

二、实际案例

用户输入一个算术表达式,如:a + b + c。我们需要实现能够解释这个算术表达式的解释器

为什么需要解释器模式,直接在一个方法中实现表达式运算不可以吗?

扩展性真的就那么好?

在这里插入图片描述

抽象表达式类

public abstract class Expression {
    public abstract int interpreter(HashMap<String, Integer> vars);
}

终结表达式

public class VarExpression extends Expression {
    private String key;

    public VarExpression(String key) {
        this.key = key;
    }

    @Override
    public int interpreter(HashMap<String, Integer> vars) {
        return vars.get(this.key);
    }
}

非终结表达式

public class AddExpression extends SymbolExpression {
    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }

    @Override
    public int interpreter(HashMap<String, Integer> vars) {
        return super.left.interpreter(vars) + super.right.interpreter(vars);
    }
}
public class SubExpression extends SymbolExpression {
    public SubExpression(Expression left, Expression right) {
        super(left, right);
    }

    @Override
    public int interpreter(HashMap<String, Integer> vars) {
        return super.left.interpreter(vars) - super.right.interpreter(vars);
    }
}

计算器类(生成语法分析树)

public class Caculator {
    private Expression expression;

    public Caculator(String expStr) {
        Stack<Expression> stack = new Stack<>();
        Expression left = null;
        Expression right = null;
        for (int i = 0; i < expStr.length(); i++) {
            switch (expStr.charAt(i)) {
                case '+':
                    left = stack.pop();
                    right = new VarExpression(expStr.valueOf(expStr.charAt(++i)));
                    stack.push(new AddExpression(left, right));
                    break;
                case '-':
                    left = stack.pop();
                    right = new VarExpression(expStr.valueOf(expStr.charAt(++i)));
                    stack.push(new SubExpression(left, right));
                    break;
                default:
                    stack.push(new VarExpression(expStr.valueOf(expStr.charAt(i))));
            }
        }
        this.expression = stack.pop();
    }

    public int run(HashMap<String, Integer> vars) {
        return expression.interpreter(vars);
    }
}

测试类

public class InterpreterTest {
    public static void main(String[] args) {
        String expStr = "a + b - c";
        Caculator caculator = new Caculator(expStr);
        HashMap<String, Integer> vars = new HashMap<>();
        vars.put("a", 1);
        vars.put("b", 2);
        vars.put("c", 3);
        System.out.println(caculator.run(vars));
    }
}

三、模式总结

优点:扩展性好

缺点:类膨胀、调试复杂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值