安卓笔记侠

专注安卓开发

导航

设计模式(十一)解释器模式

模式代码

// 抽象表达式
public abstract class AbstractExpression {
    /**
     * 抽象的解析方法
     */
    public abstract void interpret(Context ctx);
}

// 终结符表达式
public class TerminalExpression extends AbstractExpression {
    @Override
    public void interpret(Context ctx) {
        //实现文法中与终结符有关的解释操作
    }
}

// 非终结符表达式
public class NonterminalExpression extends AbstractExpression {
    @Override
    public void interpret(Context ctx) {
        //实现文法中与非终结符有关的解释操作
    }
}

// 上下文环境类,包含解释器之外的全局信息
public class Context {
}

// 客户类
public class Client {
    public static void main(String[] args) {
        //根据文法对特定句子构建抽象语法树后解释
    }
}

简单实现

需求:比如算数表达式 m + n + p。代表数字的m、n、p三个字符看成终结符号,+ 看做非终结符号。

1.抽象的算术运算解释器,为所有解释器共性的提取

public abstract class ArithmeticExpression {
    /**
     * 抽象的解析方法
     * 具体的解析逻辑由具体的子类实现
     * @return 解析得到具体的值
     */
    public abstract int interpret();
}

2.数字解释器,仅仅为了解释数字

public class NumExpression extends ArithmeticExpression{
    private int num;

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

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

3.运算符号抽象解释器,为所有运算符号解释器共性的提取

public abstract class OperatorExpression extends ArithmeticExpression {
    //声明两个成员变量存储运算符号两边的数字解释器
    protected ArithmeticExpression exp1, exp2;

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

4.加法运算抽象解释器

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

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

5.处理与解释相关的一些业务

public class Calculator {
    //声明一个Stack栈存储并操作所有相关的解释器
    private Stack<ArithmeticExpression> mExpStack = new Stack<>();

    public Calculator(String expression) {
        //声明两个TerminalExpression类型的临时变量,存储运算符左右两边的数字解释器
        ArithmeticExpression 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 AdditionExpression(exp1, exp2));
                    break;    
                default:    //如果是数字
                    //直接构造数字解释器并压入栈
                    mExpStack.push(new NumExpression(Integer.valueOf(elements[i])));
                    break;
            }
        }
    }

    public int calculate() {
        return mExpStack.pop().interpret();
    }
}

6.客户类

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

此时只是定义了加法运算,如果需要增加减法运算,则可以在 Calculator 中增加以下分支

case '-':   //如果是减号
    exp1 = mExpStack.pop();
    exp2 = new NumExpression(Integer.valueOf(elements[++i]));
    mExpStack.push(new SubtractionExpression(exp1, exp2));
    break;

此时,在 Client 中就可以开始使用了

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

 

posted on 2017-11-10 21:28  安卓笔记侠  阅读(201)  评论(0编辑  收藏  举报