23种常用设计模式之解释器模式

说明

解释器模式是一种行为型设计模式,在平时工作当中相对冷门,也非常的难于理解,可以参考正则表达式为一个实际的应用例子。虽然说解释器模式很难理解并且工作中应用很少,但是楼楼觉得解释器模式是一个非常强大且有趣的模式,因为该模式给我们提供了非常大的设计空间,我们可以在应用程序中定义自己的规则,然后去解析一些复杂的操作。

应用场景

解释器模式需要解决的是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

模式特征

角色 说明
抽象解释器(AbstractExpression) 具体的解释任务由各个实现类完成
终结符表达式(TerminalExpression) 实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结表达式,但有多个实例,对应不同的终结符。
非终结符表达式(NonterminalExpression) 文法中的每条规则对应于一个非终结表达式,非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式
上下文(Context) 上下文环境类,包含解释器之外的全局信息

代码实现


/**
 * 解释器接口
 */
public interface Expression {
    int interpreter(Context context);//一定会有解释方法
}
/**
 * 抽象非终结符表达式
 */
public abstract class NonTerminalExpression implements Expression{
    Expression e1,e2;
    public NonTerminalExpression(Expression e1, Expression e2){

        this.e1 = e1;
        this.e2 = e2;
    }
}

/**
 * 减法表达式实现类
 */
public class MinusOperation extends NonTerminalExpression {

    public MinusOperation(Expression e1, Expression e2) {
        super(e1, e2);
    }

 //将两个表达式相减
    @Override
    public int interpreter(Context context) {
        return this.e1.interpreter(context) - this.e2.interpreter(context);
    }
}


/**
 * 终结符表达式(在这个例子,用来存放数字,或者代表数字的字符)
 */
public class TerminalExpression implements Expression{

    String variable;
    public TerminalExpression(String variable){

        this.variable = variable;
    }
    @Override
    public int interpreter(Context context) {
        return context.lookup(this);
    }
}

public class PlusOperation extends NonTerminalExpression {

    public PlusOperation(Expression e1, Expression e2) {
        super(e1, e2);
    }

    //将两个表达式相加
    @Override
    public int interpreter(Context context) {
        return this.e1.interpreter(context) + this.e2.interpreter(context);
    }
}

/***
 * 上下文类(这里主要用来将变量解析成数字【当然一开始要先定义】)
 */
public class Context {
    private Map<Expression, Integer> map = new HashMap<>();

    //定义变量
    public void add(Expression s, Integer value){
        map.put(s, value);
    }
    //将变量转换成数字
    public int lookup(Expression s){
        return map.get(s);
    }
}

public class Test {
    public static void main(String[] args) {

        Context context = new Context();
        TerminalExpression a = new TerminalExpression("a");
        TerminalExpression b = new TerminalExpression("b");
        TerminalExpression c = new TerminalExpression("c");
        context.add(a, 4);
        context.add(b, 8);
        context.add(c, 2);

        System.out.println(new MinusOperation(new PlusOperation(a,b), c).interpreter(context));
    }
}

  • 结果
10

优缺点

优点

解释器是一个简单语法分析工具,它最显著的优点就是扩展性,修改语法规则只要修改相应的非终结符表达式就可以了, 若扩展语法, 则只要增加非终结符就可以了

缺点
  • 解释器模式会引起类膨胀. 每个语法都要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件, 为维护带来了非常多的麻烦
  • 解释器模式采用递归调用方法. 每个非终结符表达式之关心与自己有关的表达式,每个表达式需要知道最终的结果, 必须一层一层的剥茧,无论是面向对象的语言还是面向过程的语言,递归都是在必要条件下使用的, 它导致调试非常复杂.
  • 效率问题. 解释器模式由于使用了大量的循环和递归,效率是一个不容忽视的问题,特别是一用于解析复杂、冗长的语法时,效率是难以忍受的

参考:https://blog.csdn.net/niunai112/article/details/79982712

原创文章 67 获赞 31 访问量 5万+

猜你喜欢

转载自blog.csdn.net/u012534326/article/details/102986237