android设计模式二十三式(二十三)——解释器模式(Interpreter)

解释器模式

在一般开发中,我们很少还是用到解释器模式,但是我们都接触过,sql语句,正则,都是一个典型的解释器模式。

解释器模式中给定一个语言,定义它的规则和标识,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

先看一下解释器模式的一些成员的定义:

抽象解释器:具体的解释任务由各个实现类完成。
终结符表达式:实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结表达式,但有多个实例,对应不同的终结符。
非终结符表达式:文法中的每条规则对应于一个非终结表达式,非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式
上下文:上下文环境类,包含解释器之外的全局信息
客户端::客户端,解析表达式,构建抽象语法树,执行具体的解释操作等.

当遇到非终结符表达式的时候,就继续往里面执行,当遇到终结符表达式的时候,直接返回结果过,有点像递归的感觉。

我们还是来举个栗子:

创建一个简单的加减法计算器,那么当不用运算的时候,也就是取值的时候,属于终结符表达式,而需要运算的地方,则为非终结符表达式

/**
 * @author: hx
 * @Time: 2019/5/24
 * @Description: Context
 */
public class Context {
    private HashMap mMap = new HashMap<>();

    /**
     * 定义变量对应关系
     * @param expression
     * @param integer
     */
    public void push(Expression expression,Integer integer){
        mMap.put(expression,integer);
    }

    /**
     * 将变量转化为数字,直接返回结果,也属于终结符表达式
     * @param expression
     * @return
     */
    public int talkOut(Expression expression){
        return mMap.get(expression);
    }
}

/**
 * @author: hx
 * @Time: 2019/5/24
 * @Description: Expression
 */
public interface Expression {

    int interpreter(Context context);
}

/**
 * @author: hx
 * @Time: 2019/5/24
 * @Description: NonTeminalExpression
 */
public abstract class NonTeminalExpression implements Expression{
    protected Expression mExpression1;
    protected Expression mExpression2;

    /**
     * 非终结符表达式的父类,传入两个变量,子类对变量进行操作
     * @param expression1
     * @param expression2
     */
    public NonTeminalExpression(Expression expression1, Expression expression2) {
        mExpression1 = expression1;
        mExpression2 = expression2;
    }
}

/**
 * @author: hx
 * @Time: 2019/5/24
 * @Description: Add
 */
public class Add extends NonTeminalExpression {

    /**
     * 非终结符表达式的父类,传入两个变量,子类对变量进行操作
     *
     * @param expression1
     * @param expression2
     */
    public Add(Expression expression1, Expression expression2) {
        super(expression1, expression2);
    }

    @Override
    public int interpreter(Context context) {
        return mExpression1.interpreter(context)+mExpression2.interpreter(context);
    }
}

/**
 * @author: hx
 * @Time: 2019/5/24
 * @Description: Minus
 */
public class Minus extends NonTeminalExpression {

    /**
     * 非终结符表达式的父类,传入两个变量,子类对变量进行操作
     *
     * @param expression1
     * @param expression2
     */
    public Minus(Expression expression1, Expression expression2) {
        super(expression1, expression2);
    }

    @Override
    public int interpreter(Context context) {
        return mExpression1.interpreter(context)-mExpression2.interpreter(context);
    }
}

/**
 * @author: hx
 * @Time: 2019/5/24
 * @Description: TeminalExpression
 */
public class TeminalExpression implements Expression{

    /**
     * 这里直接取出数据,不可能还有对数据做操作,所以可以看做是终结符表达式
     * @param context
     * @return
     */
    @Override
    public int interpreter(Context context) {
        return context.talkOut(this);
    }
}

运行一下缩略型计算器

public static void main(String[] args){
    TeminalExpression t1 = new TeminalExpression();
    TeminalExpression t2 = new TeminalExpression();
    TeminalExpression t3 = new TeminalExpression();
    Context context = new Context();

    context.push(t1,5);
    context.push(t2,6);
    context.push(t3,7);

    Integer integer = new Add(t3,new Minus(t2,t1)).interpreter(context);
    System.out.println("integer="+integer);
}

输出结果:
integer=8

 解释器模式,可能有点不太好理解,我第一次学习的时候,也是一脸懵,需要慢慢去研究,细细的分析和琢磨。

就上面的文法而言,解释一下最终的计算表达式

new Add(t3,new Minus(t2,t1)).interpreter(context)

当执行new Add().interpreter(context),括号里面参数为(t3,new Minus(t2,t1)),所以.interpreter(context)方法执行,要先创建Add对象,创建Add对象,传入t3和Minus对象,这里左边t3是一个终结符表达式,所以直接返回结果,右边的Minus对象中又传入t2和t1,所以Minus对象的左边和右边都是终结符表达式,但是,因为Add对象创建的时候,右边为Minus为非终结符表达式,所以,会深一步进入Minux对象中执行Minus的.interpreter(context)方法,可以理解为递归了一级,然后Minus的.interpreter(context)执行时,左右都是终结符表达式,所以返回结果,到Add的.interpreter(context)方法,可以看成t3..interpreter(context)+(t2..interpreter(context)-t1.interpreter(context))即7+(6-5),即是终结符表达式,所以返回结算结果。

有点绕,解释器模式在开发中基本不会使用到,除非是有一些非常特殊的公司做一些特殊的任务才会用到,到时候在工作中使用锻炼,也可以很快理解,这里就不再过多描述了。

优点:

1、可扩展性比较好,灵活。

2、增加了新的解释表达式的方式。

3、易于实现简单文法。

缺点:

1、可利用场景比较少。

2、对于复杂的文法比较难维护。

3、解释器模式会引起类膨胀。

4、解释器模式采用递归调用方法。

你可能感兴趣的:(android,设计模式)