说明
解释器模式是一种行为型设计模式,在平时工作当中相对冷门,也非常的难于理解,可以参考正则表达式为一个实际的应用例子。虽然说解释器模式很难理解并且工作中应用很少,但是楼楼觉得解释器模式是一个非常强大且有趣的模式,因为该模式给我们提供了非常大的设计空间,我们可以在应用程序中定义自己的规则,然后去解析一些复杂的操作。
应用场景
解释器模式需要解决的是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
模式特征
角色 | 说明 |
---|---|
抽象解释器(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