19.Interpreter——解释器模式

demo描述:做一个计算器(显仅限加法和减法),输入要计算的公式然后输入要计算的数字,通过解释器将输入的数字翻译成输入公式中对应的参数

 

demo代码:

抽象类表达式:

public abstract class Expression {
    //公式的数据部分,用参数代替各个位置数字,将输入数字解释道对应的参数上,例:
    //输入:a+b-c
    //解释后得到:HashMap{a=10,b=20,c=40}
    //返回内容为计算得到的结果,具体运算交个子类
    public abstract int interpreter(HashMap<String ,Integer >var);
}

变量解释器:

public class VarExpression extends Expression {
    //key=a,b,c
    private String key;

    public VarExpression(String key) {
        this.key = key;
    }

    //var是{a=10,b=20,c=40}
    //根据变量名称返回对应的值
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return var.get(this.key);
    }
}

抽象预算符号解释器:

public class SymbolExpression extends Expression {
    //符号左右内容
    protected Expression left;
    protected Expression right;

    public SymbolExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    // 将符号左右数字是如何运算的推迟到具体符号类里
    // 给个默认实现
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return 0;
    }
}

加、减法解释器;

public class AddExpression extends SymbolExpression {
    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }

    //处理相加
    //var仍是{a=10,b=20,c=40}
    public int interpreter(HashMap<String, Integer> var) {
        return super.left.interpreter(var) + super.right.interpreter(var);
    }
}

public class SubExpression extends SymbolExpression {
    public SubExpression(Expression left, Expression right) {
        super(left, right);
    }

    //处理相减
    //var仍是{a=10,b=20,c=40}
    public int interpreter(HashMap<String, Integer> var) {
        return super.left.interpreter(var) - super.right.interpreter(var);
    }
}

解释执行部分:

public class Calculator {
    //定义表达式
    private Expression expression;

    public Calculator(String expStr) {
        //安排运算先后顺序
        Stack<Expression> stack = new Stack<>();
        //表达式拆分为字节数组
        char[] charArray = expStr.toCharArray();

        Expression left = null;
        Expression right = null;
        //遍历字符数组,根据不同情况做不同处理
        for (int i = 0; i < charArray.length; i++) {
            switch (charArray[i]) {
                case '+':
                    //从stack中取出left
                    left = stack.pop();
                    //取出right
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    stack.push(new AddExpression(left, right));
                    break;
                case '-':
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    stack.push(new SubExpression(left, right));
                    break;
                default:
                    //var是变量就创建VarExpression对象并push到stack
                    stack.push(new VarExpression(String.valueOf(charArray[i])));
                    break;
            }
        }
        //遍历完charArray后,stack就是最后的Expression
        this.expression = stack.pop();
    }

    public int run(HashMap<String, Integer> var) {
        //将表达式a+b和var{a=10,b=20}绑定,然后进行解释执行
        return this.expression.interpreter(var);
    }
}

客户端:

public class Client {
    public static void main(String[] args) throws IOException {
        String expStr = getExpStr();//a+b+c
        HashMap<String, Integer> var = getValue(expStr);//var {a=10,b=20,c=40}
        Calculator calculator = new Calculator(expStr);
        System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
    }

    //获得表达式
    public static String getExpStr() throws IOException {
        System.out.println("请输入表达式:");
        return (new BufferedReader(new InputStreamReader(System.in))).readLine();
    }

    //获得值映射
    public static HashMap<String, Integer> getValue(String expStr) throws IOException {
        HashMap<String, Integer> map = new HashMap<>();
        for (char ch : expStr.toCharArray()) {
            if (ch != '+' && ch != '-') {
                if (!map.containsKey(String.valueOf(ch))) {
                    System.out.println("请输入" + String.valueOf(ch) + "的值:");
                    String in =
                            (new BufferedReader(new InputStreamReader(System.in))).readLine();
                    map.put(String.valueOf(ch), Integer.valueOf(in));
                }
            }
        }
        return map;
    }
}

demo类图:

类图分析:将解释器抽象为两种,一种是变量解释器,用来将将输入的数字与公式的变量对应上;另一种是运算符号的解释器,用来将运算符号左右的数字进行运算。1处可扩展运算符,在2处加上扩展的运算符的case分支,2处可以改成工厂,让扩展更优雅

 

该demo难理解的点在:将传入的表达式改为递归层级结构,每一层都用一个具体解释器对象封装表达式左右的值,从而在计算时根据解释器对象类型找到具体的技术方式,难理解的点在构建解释器的递归层级结构

 

适用场景:编译器、运算表达式、正则表达式等适用

 

总结:解释器模式给定一个表达式,定义它的文法的一种表示,并定义一个解释器,使用该解释器来解释语言中的句子,相当于做了一个转换。

 

它包含以下角色:

Context:环境角色,含有解释器之外的全局信息

AbstractExpression:抽象表达式,声明一个抽象的解释操作,这个方法为抽象语法树中所有节点所共享

TerminalExpression:中介符表达式,为文法中的中介符实现解释操作

NonTermialExpression:非中介符表达式,为文法中的非中介符实现解释操作

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值