《Android 源码设计模式解析与实战》读书笔记 (十) 《Android 源码设计模式解析与实战》PDF 资料下载

一、解释器模式的简介

解释器模式是一种行为型模式,其提供了一种解释语言的语法或表达式的方式,该模式定义了一个表达式接口,通过该接口解释一个特定的上下文。

1.1、定义

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

1.2、使用场景

  1. 如果某个简单的语言需要解释执行而且可以将该语言中的语句表示为一个抽象语法树时可以考虑使用解释器模式;
  2. 在某些特定的领域出现不断重复的问题时,可以将该领域的问题转化为一种语法规则下的语句,然后构建解释器来解释该语句。

二、解释器模式的简单实现

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 <span class="hljs-function"><span class="hljs-title">interpret</span></span>() {
    <span class="hljs-built_in">return</span> 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 AdditionExpressiom extends OperatorExpression {
    public AdditionExpressiom(ArithmeticExpression exp1, ArithmeticExpression exp2) {
        super(exp1, exp2);
    }
@Override
public int <span class="hljs-function"><span class="hljs-title">interpret</span></span>() {
    <span class="hljs-built_in">return</span> exp1.interpret() + exp2.interpret();
}

}

复制代码
public class Calcultator {
    //声明一个Stack栈存储并操作所有相关的解释器
    private Stack<ArithmeticExpression> mExpStack = new Stack<>();
public Calcultator(String expression) {
    //声明两个ArithmeticExpression类型的临时变量,存储运算符左右两边的数字解释器
    ArithmeticExpression exp1, exp2;

    //根据空格分割表达式字符串
    String[] elements = expression.split(<span class="hljs-string">" "</span>);

    /**
     * 循环遍历表达式元素数组
     */
    <span class="hljs-keyword">for</span> (int i = 0; i &lt; elements.length; i++) {
        /**
         * 判断运算符号
         */
        switch (elements[i].charAt(0)) {
            <span class="hljs-keyword">case</span> <span class="hljs-string">'+'</span>://如果是加号
                //则将栈中的解释器弹出作为运算符号左边的解释器
                exp1 = mExpStack.pop();
                //同时将运算符号数组下标下一个元素构造为一个数字解释器
                exp2 = new NumExpression(Integer.valueOf(elements[++i]));
                //通过上面两个数字解释器构造加法运算解释器
                mExpStack.push(new AdditionExpressiom(exp1, exp2));
                <span class="hljs-built_in">break</span>;
            default://如果为数字
                /**如果不是运算符则为数字
                 * 若是数字,直接构造数字解释器并压入栈
                 */
                mExpStack.push(new NumExpression(Integer.valueOf(elements[i])));
                <span class="hljs-built_in">break</span>;
        }
    }
}

/**
 * 计算结果
 */
public int <span class="hljs-function"><span class="hljs-title">calculate</span></span>() {
    <span class="hljs-built_in">return</span> mExpStack.pop().interpret();
}

}

复制代码
Calcultator c = new Calcultator("153 + 3589 + 118 + 555");
        System.out.println(c.calculate());
复制代码

输出结果:

4415
复制代码

三、总结

3.1、优点

解释器模式最大的优点是其灵活的扩展性,当想对文法规则进行扩展延伸时,只需要增加相应的非终结符解释器,并在构建抽象语法树时,使用到新增的解释器对象进行具体的解释即可,非常方便。

3.2、缺点

因为对每一条文法都可以对应至少一个解释器,其会生成大量的类,导致后期维护苦难。同时,过于复杂的文法,构建其抽象语法树会显得异常繁琐,甚至有可能会出现需要构建多棵抽象语法树的情况。因此,对于复杂的文法并不推荐使用解释器模式。

学海无涯苦作舟

我的微信公众号

  • Android

    开放手机联盟(一个由 30 多家科技公司和手机公司组成的团体)已开发出 Android,Android 是第一个完整、开放、免费的手机平台。

    293 引用
感谢    赞同    分享    收藏    关注    反对    举报    ...