Android中的设计模式之解释器模式

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 参考《设计模式:可复用面向对象软件的基础 》5.3 Interpreter 解释器 类行为型模式《Android源码设计模式解析与实战》第10章 化繁为简的翻译机--解释器模式意图给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器适用该表示来解释语言中的句子。

参考

  • 《设计模式:可复用面向对象软件的基础 》5.3 Interpreter 解释器 类行为型模式
  • 《Android源码设计模式解析与实战》第10章 化繁为简的翻译机--解释器模式

意图

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

适用场景

当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:

  • 该文法简单对于复杂的文法,文法的类层次变得庞大而又无法管理。
  • 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换为另一种形式。

非终结符号与终止符号

例:

S ::= abA*ef
A ::= cd

符号“::=”表示推导;符号“*”表示闭包,意思就是符号A可以有0或有N个重复;S和A称为非终结符号,因为他们能推导出式子右边的表达式,同时又因为整个推导式是从S出发的,因此,这个S也称为初始符号;而abef和cd这些字符不能再被推导我们称之为终结符号。

结构

interpreterPattern
  • AbstractExpression 抽象表达式,声明一个抽象的解释操作父类,并定义了一个抽象的解释方法,其具体的实现在各个具体的子类解释器中完成。
  • TeminalExpression 终结符表达式,实现文法中与终结符有关的解释操作。
  • NonterminalExpression 非终结符表达式,实现文法中与非终结符有关的解释操作。
  • Context 上下文环境类,包含解释器之外的全局信息。
  • Client 客户端类,解析表达式,构建抽象语法树,执行具体的解释表达操作等。

优点

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

缺点

每一条文法都对应一个解释器,会生成大量类,导致后期维护困难。同时,对于过于复杂的文法,构建其抽象语法树会显得异常繁琐,因此,对于复杂的文法并不推荐使用解释器模式。

例子1

描述

表达式“m+n+p”,如果我们使用解释器模式对该表达式进行解释,那么代表数字的m,n,和p三个字母我们就可以看成是终结符号,而“+”这个算术运算符号则可当作非终结符,同时我们可以先创建一个抽象解释器表示数学运算。

结构

结构

代码实现


/**
 *  算术运算解释器抽象类
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:22
 */
public  abstract  class AthmeticExpression {
    /**
     * 抽象的解析方法
     * @return 解析得到的值
     */
    abstract int interpreter();
}

/**
 *  数字解释器,只为了解释数字
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:24
 */
public class NumExpression extends AthmeticExpression {
    private int num;
    public NumExpression(int num){
        this.num = num;
    }
    @Override
    int interpreter() {
        return num;
    }
}


/**
 *  运算符解释器
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:27
 */
public abstract class OperatorExpression extends AthmeticExpression {
    /**
     * 运算符两边的表达式
     */
    protected AthmeticExpression exp1,exp2;

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

}

/**
 *  加法解释器
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:29
 */
public class AdditionExpressoin extends OperatorExpression {
    public AdditionExpressoin(AthmeticExpression exp1, AthmeticExpression exp2) {
        super(exp1, exp2);
    }

    /**
     * 具体解释+符号
     * @return 解释结果
     */
    @Override
    int interpreter() {
        return exp1.interpreter()+exp2.interpreter();
    }
}


/**
 *  计算器类
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:30
 */
public class Calculator {
    /**
     * 用一个栈存储并操作所有相关的解释器
     */
    private Stack<AthmeticExpression> mExpStack = new Stack<>();

    public Calculator(String  expression){
        AthmeticExpression exp1,exp2;
        // 以空格分开元素
        String[] elements = expression.split(" ");
        for (int i = 0;i<elements.length;i++){
            switch (elements[i].charAt(0)){
                // 如果为‘+’
                case '+':
                    // 将栈中的解释器弹出作为运算符左边的解释器
                    exp1 = mExpStack.pop();
                    // 同时将运算符数组下标下一个元素构造为一个数字解释器
                    exp2 = new NumExpression(Integer.valueOf(elements[++i]));
                    mExpStack.push(new AdditionExpressoin(exp1,exp2));
                    break;
                    default:
                        // 如果为数字
                        mExpStack.push(new NumExpression(Integer.valueOf(elements[i])));
                        break;
            }
        }
    }

    /**
     * 最终结算结果
     * @return
     */
    public int calculate(){
        return mExpStack.pop().interpreter();
    }
}

public static void main(String[] args){
        Calculator calculator = new Calculator("3 + 8 + 2");
        System.out.println(calculator.calculate());
    }

输出结果:

13

应用例子2 Android源码中的PackageParser

目录
相关文章
|
设计模式 移动开发 数据库
行为型设计模式10-解释器模式
行为型设计模式10-解释器模式
100 1
|
3月前
|
设计模式 存储 缓存
Java设计模式 - 解释器模式(24)
Java设计模式 - 解释器模式(24)
|
7月前
|
设计模式 SQL Java
【设计模式】抖音一面:你不知道解释器模式?
【设计模式】抖音一面:你不知道解释器模式?
51 1
|
7月前
|
设计模式 Go
[设计模式 Go实现] 行为型~解释器模式
[设计模式 Go实现] 行为型~解释器模式
|
7月前
|
设计模式 存储 Java
小谈设计模式(28)—解释器模式
小谈设计模式(28)—解释器模式
|
7月前
|
设计模式 存储 Java
23种设计模式,解释器模式的概念优缺点以及JAVA代码举例
【4月更文挑战第7天】解释器模式是一种行为设计模式,它用于定义一个语言的语法表示,并提供一个解释器来处理这种语法。主要用于频繁需要解释执行一组固定语法规则的场景,例如编程语言解释器、规则引擎等。
47 3
|
7月前
|
设计模式 存储 SQL
【设计模式系列笔记】解释器模式
解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言的文法,并且建立一个解释器来解释该语言中的句子。在Java中,解释器模式通常用于实现编程语言解释器、正则表达式解释器等。
67 0
|
7月前
|
设计模式
【设计模式】解释器模式
【设计模式】解释器模式
|
7月前
|
设计模式 监控 Java
聊聊Java设计模式-解释器模式
解释器模式(Interpreter Design Pattern)指给定一个“语言”,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。这里所指的“语言”是指使用规定格式和语法的代码。
84 4
聊聊Java设计模式-解释器模式
|
7月前
|
设计模式 Go 开发工具
Golang设计模式——18解释器模式
Golang设计模式——18解释器模式
52 0
Golang设计模式——18解释器模式