一天一个设计模式---解释器模式

介绍:给定一种语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的例子。

一、角色及作用

可能上面对解释器模式的解释十分难以理解,为什么我们写代码又和语言有关了。这里我举个例子

你是大神
你是高富帅

这里可以解释成 - 你是[名词]的形式

我是菜鸟
我是穷矮丑

结合上面,我们可以解释成 - [名词]是[名词]的形式

角色作用
抽象表达式抽象的解释操作父类,并定义一个抽象的解释方法
终结符表达式实现文法中与元素相关联的解释操作,比如 A + B 这里A,B是终结符
非终结符表达式实现文法中与非终结符有关的解释操作,非终结符表达式一般是文法中的运算符或者其他关键字
环境类包含解释器之外的全局信息

二、打造加法计算器

抽象表达式

public abstract class ArithmeticExpression {
    public abstract int interpret();
}

数字解释器,终结符表达式

public class NumExpression extends ArithmeticExpression {
    private int num;

    public NumExpression(int num) {
        this.num = num;
    }

    @Override
    public int interpret() {
        return num;
    }
}

运算符抽象解释器,因为有多种运算符,方便以后维护

public abstract class OperatorExpression extends ArithmeticExpression {
    protected ArithmeticExpression exp1, exp2;

    public OperatorExpression(ArithmeticExpression exp1, ArithmeticExpression exp2) {
        this.exp1 = exp1;
        this.exp2 = exp2;
    }
}

加法解释器,非终结符表达式

public class AdditionExpression extends OperatorExpression {

    public AdditionExpression(ArithmeticExpression exp1, ArithmeticExpression exp2) {
        super(exp1, exp2);
    }

    @Override
    public int interpret() {
        return exp1.interpret() + exp2.interpret();
    }

}

计算器,环境类

public class Calculator {
    // 使用stack,后进先出,记录所有操作
    private Stack<ArithmeticExpression> stack = new Stack<ArithmeticExpression>();

    // 这里规定好,数字和符号之间用空格分隔
    public int calculate(String exp) {
        String[] eles = exp.split(" ");
        for (int i = 0; i < eles.length; i++) {
            NumExpression front = null; // 保留运算符前面的值
            NumExpression next = null;// 保留运算符后面的值
            switch (eles[i]) {
            case "+":
                front = (NumExpression) stack.peek();
                next = new NumExpression(Integer.valueOf(eles[++i]));
                stack.push(next);
                stack.push(new AdditionExpression(front, next));
                break;
            default:
                // 其他为数字
                stack.push(new NumExpression(Integer.valueOf(eles[i])));
                break;
            }
        }
        return stack.peek().interpret();
    }
}

三、我们还需要减法

增加减法,十分方便!

减法解释器

public class SubtractExpression extends OperatorExpression {

    public SubtractExpression(ArithmeticExpression exp1, ArithmeticExpression exp2) {
        super(exp1, exp2);
    }

    @Override
    public int interpret() {
        return exp1.interpret() - exp2.interpret();
    }
}

计算器

...
...
case "-":
    front = (NumExpression) stack.peek();
    next = new NumExpression(Integer.valueOf(eles[++i]));
    stack.push(next);
    stack.push(new SubtractExpression(front, next));
    break;
...
...

四、看看结果

Calculator c = new Calculator();
System.out.println(c.calculate("1 + 4"));
System.out.println(c.calculate("1 - 4"));

输出

5
-3

总结:解释器模式能灵活地实现扩展,实现时只需要增加非终结符来实现相关业务。缺点也是类的数量的膨胀,对于负责的文法,解释器的结构树也会十分负责,难以维护


更多模式:一天一个设计模式—分类与六大原则

更多源码: https://github.com/oDevilo/Java-Base

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值