今天的博客主题
设计模式 ——》 设计模式之解释器模式
给定一门语言,定义它的一种文法表示,并定义一个解释器,用来解释语言中的句子。
这种模式一般被用在SQL的解析,符号的处理等。
解释器模式也是一种使用频率低学习难度较大的一个设计模式。
1)一些重复出现的问题可以用一种简单的语言来进行表达。
2)一个简单语法需要解释的场景。
3)编译器,运算表达式的计算
4)
1)扩展性好,比较灵活。
2)增加了新的解释表达式的方式。
3)易于实现简单的文法。
4)
1)可以用的场景较少。
2)对于复杂的文法比较难易维护。
3)语法规则复杂时,会引起类膨胀的问题。因为每个语法都需要产生一个非终结符表达式,语法复杂时,就会产生大量的解释类,增加系统的复杂性。
4)执行效率较低,解释器模式是采用递归调用方法,每个非终结符表达只关心与自己有关的表达式,每个表达式都需要知道最终的结果,因此完整表达式的最终结果是通过从后往前递归调用的方式获取得到的。所以说表达式复杂的时候,层级嵌套深,解释效率就会低。
解释器模式主要有以下几个角色
抽象表达式(Expression):定义一个解释方法,由具体的子类去解释。
终结符表达式(TerminalExpression):实现文法中与终结符有关的解释。句子中的每一个终结符都是该类的实例。通常一个解释器模式中只有少数几个终结符表达式,可通过非终结符表达式组成复杂的句意。
非终结符表达式(NontermianlExpression):实现文法中与非终结符有关的解释。非终结符表达式可以包含终结符表达式,也可以包含非终结符表达式,一般通过递归实现完成。
上下文类(Context):上下文环境类,主要包含解释器之外的一些全局信息。
什么是终结符?什么是非终结符?
比如公式 a + b = c; 那 a b 就是终结符,+ 就是非终结符
那括号 “()” 是终结符还是非终结符呢???
模仿去写一个 + - * / 的计算,意义不大,1+2+3*3-2+1
套上一层括号,能写出来,那就很可以了,1+(2+3)*3-(2+1)
但一般的写法如下
// 抽象表达式 abstract class Expression{ abstract void interpret(Context context); } // 终结符表达式 class TerminalExpression extends Expression{ @Override void interpret(Context context) { System.out.println("终结符表达式解释"); } } // 非终结符表达式 class NonterminalExpression extends Expression{ private Expression left; private Expression right; public NonterminalExpression(Expression left, Expression right){ this.left = left; this.right = right; } @Override void interpret(Context context) { /** * 递归调用每一个组成部分的interpret()方法 * 在递归调用时指定组成部分的连接方式,即非终结符的解释操作 */ } } // 上下文环境类 class Context{ // 存储全局信息 private Map<String, String> map = new HashMap<>(); public void register(String k, String v){ // 往上下文环境类中设值 map.put(k,v); } public String get(String k){ // 获取存储在环境类中的值 return map.get(k); } }