解释器模式(Interpreter Pattern)

解释器模式(Interpreter Pattern)
  • 优点
    1、可扩展性好。
    2、易于实现。

  • 缺点
    1、执行效率较低。模式通常使用大量循环和递归调用,解释复杂句子时,运行速度很慢。
    2、会引起类膨胀。模式中每条规则至少需要定义一个类,语法规则很多时,类的个数将急剧增加,导致系统难以管理与维护。
    3、应用的场景少。JAVA 中如果碰到可以用 expression4J 代替。

  • 模式中主要角色
    抽象表达式:定义一个抽象解释方法。
    非终结表达式:实现语法中与非终结符有关的解释操作。
    终结表达式:实现语法中与终结符有关的解释操作。
    客户类:解析表达式。

  • 例子:加减法的实现,类图如下:
    在这里插入图片描述

  • 代码实现

抽象表达式

public interface AbstractExpression {
    double interpret();
}

非终结表达式

/**
 * 加法解释器
 */
public class AddExpression implements AbstractExpression {
    private AbstractExpression left;

    private AbstractExpression right;

    public AddExpression(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public double interpret() {
        return left.interpret() + right.interpret();
    }
}
/**
 * 减法解释器
 */
public class SubExpression implements AbstractExpression {
    private AbstractExpression left;

    private AbstractExpression right;

    public SubExpression(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public double interpret() {
        return left.interpret() - right.interpret();
    }
}

终结表达式

public class TerminalExpression implements AbstractExpression {
    private String value;

    public TerminalExpression(String value) {
        this.value = value;
    }

    @Override
    public double interpret() {
        return Double.valueOf(value);
    }
}

客户类

public class Client {
    //声明一个stack栈存储并操作所有相关的解释器
    private AbstractExpression mExpStack;

    public Client(String expression) {
        //定义两个临时变量
        AbstractExpression exp1, exp2;

        //根据空格分割表达式字符串
        String[] elements = expression.split(" ");

        //循环遍历元素
        for (int i = 0; i < elements.length; i++) {
            switch (elements[i].charAt(0)){
                case '+':
                    exp1 = mExpStack;
                    exp2 = new TerminalExpression(elements[++i]);
                    mExpStack = new AddExpression(exp1,exp2);
                    break;
                case '-':
                    exp1 = mExpStack;
                    exp2 = new TerminalExpression(elements[++i]);
                    mExpStack = new SubExpression(exp1,exp2);
                    break;
                default:
                    mExpStack = new TerminalExpression(elements[i]);
                    break;
            }
        }
    }

    public double calculate(){
        return mExpStack.interpret();
    }
}

测试

public class Test {
   public static void main(String[] args) {
       String expression = "10 + 3 + 1 + 2.6 - 12 - 1 + 13 + 13";
       Client c = new Client(expression);
       System.out.println(expression + " = " + c.calculate());
   }
}
// 运行结果
10 + 3 + 1 + 2.6 - 12 - 1 + 13 + 13 = 29.6
  • 应用场景
    1、当语言的语法较为简单,且执行效率不是关键问题时。
    2、当问题重复出现,且可以用一种简单的语言来进行表达时。
    3、当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候,如 XML 文档解释。
    注意:解释器模式在实际的软件开发中使用比较少,因为它会引起效率、性能以及维护等问题。如果碰到对表达式的解释,在 Java 中可以用 Expression4J 或 Jep 等来设计。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值