设计模式--第19篇(解释器模式)

一,解释器模式

解释器模式:

  1. 给一个语言表达式,定义它的文法的一种表示,并定义一个解释器,使用该解释器来解释语言中的表达示;
  2. 在编译原理中,一个表达式通过词法分析器形成词单元,而后这些词单元再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树,这些语法分析器和词法分析器都可以看做解释器;
  3. 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树,一些重复出现的问题可以用一种简单的语言来表示,一个简单语法需要解释的等场景;

二,原理类图

在这里插入图片描述
意图: 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用性:
当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。

三,实例

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

package com.neei.interpreter;

import java.util.Map;
import java.util.Stack;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/17  22:25
 * @Description: 游学网
 * @throws:
 */
public class Calculator {

    private Expression expression;


    public Calculator(String expStr) {
        Stack<Expression> stack = new Stack<>();
        char[] chars = expStr.toCharArray();
        Expression left = null;
        Expression right = null;
        for (int i = 0; i < chars.length; i++) {
            switch (chars[i]) {
                case '+':
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(chars[++i]));
                    stack.push(new AddExpression(left, right));
                    break;
                case '-':
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(chars[++i]));
                    stack.push(new SubExpression(left, right));
                    break;
                default:
                    stack.push(new VarExpression(String.valueOf(chars[i])));
            }
            this.expression = stack.pop();
        }
    }

    public int run(Map<String,Integer> var){
        return this.expression.interpreter(var);
    }
}

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

package com.neei.interpreter;

import java.util.Map;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/17  22:16
 * @Description: 游学网
 * @throws:
 */
public abstract class Expression {
    /**
     *a+b-c
     * @param var key:表达式参数[a,b,c],value:值10,20...
     *            var={a=10,b=20}
     * @return
     */
    abstract int interpreter(Map<String, Integer> var);
}

TerminalExpression: 终结符表达式,实现与文法中的终结符相关的解释操作;

package com.neei.interpreter;

import java.util.Map;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/17  22:18
 * @Description: 游学网
 * @throws:
 */
public class VarExpression extends Expression {
    /**
     * key=a,key=b....
     */
    private String key;

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

    @Override
    int interpreter(Map<String, Integer> var) {
        return var.get(key);
    }
}

NonTerminalExpression: 非终结符表达式,实现与文法中的非终结符相关的解释操作;

package com.neei.interpreter;

import java.util.Map;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/17  22:17
 * @Description: 游学网
 * @throws:
 */
public class SymbolExpression extends Expression {

    protected Expression left;
    protected Expression right;

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

    @Override
    int interpreter(Map<String, Integer> var) {
        return 0;
    }
}
public class AddExpression extends SymbolExpression {
    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }
    @Override
    int interpreter(Map<String, Integer> var) {
        return left.interpreter(var) + right.interpreter(var);
    }
}

public class SubExpression extends SymbolExpression {
    public SubExpression(Expression left, Expression right) {
        super(left, right);
    }
    @Override
    int interpreter(Map<String, Integer> var) {
        return super.left.interpreter(var)-super.right.interpreter(var);
    }
}

Stack栈相关知识回顾

四,源码分析

Spring源码中使用的解释器模式,如org.springframework.expression.spel.standard.SpelExpression

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值