[把你的理性思维慢慢变成条件反射]
本文,我们讲介绍解释器模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:
操作系统:win7 x64
其他软件:eclipse mars,jdk8
-------------------------------------------------------------------------------------------------------------------------------------
经典问题:
计算器,正则表达式,具有“翻译解释器”功能的应用或组件,如控制器,浏览器将前端文件转变为页面等。
思路分析:
要点一:解释器能够区分出终结符与非终结符
要点二:解释器能够完全识别并翻译输入的表达式。
示例工程:
解释器模式模板代码:
创建AbstractExpression.java文件,具体内容如下:
package com.csdn.ingo.gof_Interpreter;
public abstract class AbstractExpression {
public abstract void Interpret(Context context);
}
创建Context.java文件,具体内容如下:
package com.csdn.ingo.gof_Interpreter;
public class Context {
public String obj;
private String condition;
private String status;
private String params;
public String getObj() {
return obj;
}
public void setObj(String obj) {
this.obj = obj;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
}
创建NonterminalExpression.java文件,具体内容如下:
package com.csdn.ingo.gof_Interpreter;
public class NonterminalExpression extends AbstractExpression{
@Override
public void Interpret(Context context) {
System.out.println("非终端解释器");
}
}
创建TerminalExpression.java文件,具体内容如下:
package com.csdn.ingo.gof_Interpreter;
public class TerminalExpression extends AbstractExpression {
@Override
public void Interpret(Context context) {
System.out.println("终端解释器");
}
}
创建Window.java文件,具体内容如下:
package com.csdn.ingo.gof_Interpreter;
import java.util.ArrayList;
import java.util.List;
public class Window {
public static void main(String[] args) {
Context context = new Context();
List<AbstractExpression> list = new ArrayList<AbstractExpression>();
list.add(new TerminalExpression());
list.add(new NonterminalExpression());
list.add(new TerminalExpression());
list.add(new TerminalExpression());
for(AbstractExpression abe:list){
abe.Interpret(context);
}
}
}
【上面的代码直接看的话,可能有难度。先把代码提供给各位看官是希望现将代码运行起来,观察结果。下面我们介绍相关的概念与原理】
模式总结:
解释器模式结构图:
什么是句子:
- 由词,词组构成的,能够完整表达意思的语言单位。在计算机语言中,一个句子可以是一个计算表达式,一段代码等。
什么是文法规则:
- 即句子的组成规则,在计算机中,特指:四元组【非终结符号,终结符号,产生式规则,起始符号】。通俗的将是指每一个句子的组织办法。
什么是抽象语法树:
- 是指源码的抽象语法结构的树状表现形式。树中的每一个节点都表示源代码中的一种结构。之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法出现的每个细节。比如,“{}”被隐藏在输的结构中,并没有以输的节点形式呈现。而类似于“if...else...”语句则使用两个分支节点来代替。
解释器模式(interpreter):
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
组成部分:
- AbstractExpression(抽象表达式):声明一个抽象的解释操作,是所有TerminalExpression(终结符表达式)与NonterminalExpression(非终结符表达式)的公共父类。
- TerminalExpression(终结符表达式):实现与文法中的终结符相关联的解释操作。实现了AbstractExpression(抽象表达式)中声明的接口。文法中的每一个终结符都有一个具体的终结符表达式与之相对应。
- NonterminalExpression(非终结符表达式):为文法中的非终结符实现解释操作。对文法中每一条规则R1,R2,,,Rn都需要一个具体的非终结符表达式类。通过实现抽象表达式的interpret()方法时间解释操作。解释操作以递归的方式调用上面所提到的代表R1,R2,,,Rn中各个符号的示例变量。
- Context(环境类):存储解释器之外的全局信息,通常用于存储临时需要解释的语句。(其中通常有集合类型的属性)
反思:
应用场景:
- 如果一种特定类的问题发生的频率足够高,那么可能就值得将问题的各个示例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
- 一个语言的文法较为简单,可以将一个需要执行的句子表示为一个抽象语法树。
- 执行效率可以不作为第一优先级问题考虑
优点:
- 容易改变和扩展文法,因为该模式使用类来表示文法规则,可以通过继承来改变或扩展该文法。
- 具体实现时,因为定义抽象语法树中各个节点的类的实现大致相似。方便直接编写或使用自动化工具生成。
- 每一个文法规则都是一个具体的类,方便的实现一个简单的语言的解释。并且,在新增解释表达式时,只需增加对应的(非)终结符表达式类即可。
缺点:
- 对于复杂文法的句子,每一个规则都需要定义一个类,并且文法规则之间的相互关系也需要精心设计。有可能导致解释器难以管理和维护。需要在适当的时机采用语法分析程序来取代解释器模式。
- 由于递归调用,大量循环调用。在面对复杂的句子时,执行效率可能会受到影响。
-------------------------------------------------------------------------------------------------------------------------------------
至此,被说了很多遍的设计模式---解释器模式 结束
特别备注:
解释器模式是一个使用频率较低的设计模式。在此,仅作为学习档案记录下来,以备不时之需。各位看官如果对此模式有深入了解的需求,建议寻找更为详尽的学习资料查阅。
参考资料:
图书:《大话设计模式》
其他博文:http://blog.csdn.NET/lovelion/article/details/7563445