定义
解释器模式(Interpreter Pattern)指的是给定一种语言,定义它的文法的一种表示,并定义一个解释器,这个解释器就是被用来解释这门指定语言中句子。它是一种类行为型模式。
解释器模式类似于计算机的语言的解释器的作用,比如你定义一种语言,然后定义它的一种文法的表示,解释器的作用就是用来解释这门语言的句子,比如定义的语言中#表示我,¥表示你,%表示和,那么#%¥就会被解释器解释成我和你的意思。
这里涉及到了编译原理中的:文法、句子和语法树的概念。
文法:用于描述语言的语法结构的形式规则。比如中文中的主谓宾的语法结构。
句子:就是普通的元素,我们说的话写的文字基本都是句子,它是语言的基本单位,比如这段文字就是一个句子。
语法树:它是句子结构的一种树型表示,它代表了句子的推导结果,它有利于理解句子语法结构的层次。
组成部分
解释器模式主要由以下几个部分组成:
1、抽象表达式(Abstract Expression):声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中约定解释器的解释操作,主要包含一个解释方法interpret()方法。具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器NonterminalExpression完成。
2、终结符表达式类(Terminal Expression):是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应
3、非终结符表达式类(Nonterminal Expression):文法中的每条规则对应于一个非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
4、环境类(Context):主要包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值
例子
首先定义一个抽象的表达式类:
public abstract class AbstractExpression { public abstract boolean interpreter(String string); } 复制代码
终结符表达式类:
public class TerminalExpression extends AbstractExpression { private Set<String> set = new HashSet<String>(); public TerminalExpression(String[] strings) { for (int i = 0; i < strings.length; i++) { set.add(strings[i]); } } @Override public boolean interpreter(String string) { if(set.contains(string)){ return true; }else{ return false; } } } 复制代码
非终结符表达式:
public class NonterminalExpression extends AbstractExpression { private AbstractExpression person = null; private AbstractExpression thing = null; public NonterminalExpression(AbstractExpression person, AbstractExpression thing) { this.person = person; this.thing = thing; } @Override public boolean interpreter(String string) { return person.interpreter(string)&&thing.interpreter(string); } } 复制代码
环境类:
public class Context { private String[] persons = {"小明","小红","小白"}; private String behaverior = "吃"; private String[] things = {"鸡翅","汉堡","牛排"}; private AbstractExpression exp; public Context() { //数据初始化 AbstractExpression personexp = new TerminalExpression(persons); AbstractExpression thingexp = new TerminalExpression(things); exp = new NonterminalExpression(personexp,thingexp); } public void operation(String string) { //调用相关表达式类的解释方法 boolean flag = exp.interpreter(string); if(!flag){ System.out.println(string+"吃汉堡"); }else{ System.out.println(string+"不吃汉堡"); } } } 复制代码
测试方法:
public class InterpreterPatternTest { public static void main(String[] args) { Context context= new Context(); context.operation("小明"); } } 复制代码
运行结果:
解释器模式的优点
解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,如果需要扩展语法,你只需要增加非终结符类就可以了,所以拓展性好。
解释器模式的缺点
1、解释器模式的语法规则比较复杂,每个语法都需要指定一个具体的非终结符表达式。所以容易造成代理量过大,而且维护比较复杂。
2、解释器模式需要知道它具体的文法,否则逻辑理解较为复杂。
应用场景
解释器模式在应用中比较少,只有在一些重复发生的计算法则,或者sql语句可以使用解释器进行解释
总结
抽象表达式是生成语法集合的关键,每个非终结符表达式解释一个最小的语法单元,然后通过递归的方式将这些语法单元组合成完整的文法,这就是解释器模式。
解释器模式在实际的使用中比较少,因为它的维护和性能效率是比较复杂的问题,所以对于解释器模式了解即可。
最后本文以及之前的所有的设计模式中的例子代码,都将同步至github,需要的欢迎下载star。