人物:大鸟,小菜
事件:小菜给大鸟说领导找他谈话,说他工作不错,说另一个同事梅星工作一般,大鸟说小菜没有领会到领导的言外之意,其实领导是侧面告诉小菜,你干的不错,后面可能需要你多加加油,工作量可能提一提,而同事梅星工作一般,可能领导对他不是很满意。小菜觉得职场太复杂要是有个翻译器就好了,大鸟顺之引出了解释器模式。
解释器模式:
1.介绍了解释器模式的概念
2.结构图
3.解释器模式代码
4.好处与不足
5.小结
解释器模式
1.概念:给定一个语言(巫师世界的语言),定义它的文法的一种表示(麻瓜),并定义一个解释器(罗纳德·比利尔斯·韦斯莱),这个解释器使用该表示来解释言语中的句子(不懂魔法的人类)
2.结构图:
注:
(1)终结符:终结符直接就代表一个意思,是不可拆分的最小元素,比如关键字if就不能再分成i和f了。
(2)非终结符:非终结符可以再分成更细的东西,且不是终结符的都是非终结符。
3.代码示意:
前情提要:
(1)什么是语法树:是源代码的抽象语法结构的树状表现形式
(2)举例:foo = 'hello world';
AbstractExpression类,声明一个抽象的解释操作,这个接口为抽象语法树共享:
public abstract class AbstractExpression { public abstract void interpret(Context context); }
TerminalExpression类,实现抽象表达式中所有接口,主要是一个interpret方法,文中每一个终结符都有一个具体终结表达式与之对应:
@Slf4j public class TerminalExpression extends AbstractExpression { @Override public void interpret(Context context) { log.info("终端解释器"); } }
NonterminalExpressionl类,非终结符表达式,为文中非终结符实现解释操作:
@Slf4j public class NonterminalExpression extends AbstractExpression { @Override public void interpret(Context context) { log.info("非终端解释器"); } }
Context类,包含解释器之外的一些全局信息:
@Data public class Context { private String input; private String output; }
客户端代码,构建表示该文法定义的语言中一个特定的句子的抽象语法树,调用解释操作:
public class ExpressionClient { public static void main(String[] args) { Context context = new Context(); List<AbstractExpression> list = new ArrayList<>(); list.add(new TerminalExpression()); list.add(new NonterminalExpression()); list.add(new TerminalExpression()); list.add(new TerminalExpression()); for (AbstractExpression exp : list) { exp.interpret(context); } } }
4.好处:用解释器模式,意味着很容易地改变和扩展文法(即语法),因为该模式使用类来标识文法规则,你可以使用继承来改变或扩展该文法,也比较容易实现文法,因为定义抽象语法树中各节点的类的实现大体类似,这些类都易于直接编写。
不足:解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。所以建议当文法复杂时,使用其他程序如语法分析程序或编译器生成器来处理。
5.小结:解释器模式就是把一串可能看不懂的字符串,通过一系列规则,转化成看得懂的信息,或者是把我们常用的信息,通过规则转化,转成机器或者代码看得懂的指令。