1、定义
给定一个语言,定义一个文法的一种表示, 并定义一个解释器, 这个解释器使用该表示来解释语言中的句子。
如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子,这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
就比如正则表达式,它就是解释器模型的一种应用,解释器为正则表达式定义了一个文法,如何表示一个特定的正则表达式,以及如何解释这个正则表达式。
2、使用场景
2.1、当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树,可以使用解释器模式。而当存在以下情况时该模式效果最好
2.2、该文法的类层次结构变得庞大而无法管理。此时语法分析程序生成器这样的工具是最好的选择。他们无需构建抽象语法树即可解释表达式,这样可以节省空间而且还可能节省时间。
2.3、效率不是一个关键问题,最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将他们装换成另一种形式,例如,正则表达式通常被装换成状态机,即使在这种情况下,转换器仍可用解释器模式实现,该模式仍是有用的。
3、优缺点
3.1、优点:
3.1.1、 可以很容易地改变和扩展方法, 因为该模式使用类来表示方法规则, 你可以使用继承来改变或扩展该方法。
3.1.2、也比较容易实现方法, 因为定义抽象语法树总各个节点的类的实现大体类似, 这些类都易于直接编写。
3.1.3、解释器模式就是将一句话,转变为实际的命令程序执行而已。 而不用解释器模式本身也可以分析, 但通过继承抽象表达式的方式, 由于依赖转置原则, 使得文法的扩展和维护都带来的方便。
3.2、缺点:
解释器模式为方法中的每一条规则至少定义了一个类, 因此包含许多规则的方法可能难以管理和维护。 因此当方法非常复杂时, 使用其他的技术如 语法分析程序 或 编译器生成器来处理。
4、应用实例
- 编译器
- 运算表达式计算、正则表达式
- 机器人
5、实现
5.1、抽象表达式
/**
* desc: 抽象表达式是生成语法集合(语法树)的关键,每个语法集合完成指定语法解析任务,
* 它是通过递归调用的方式,最终由最小的语法单元进行解析完成。
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/15 10:01
*/
public abstract class AbstractExpression {
public abstract boolean interpret(String context);
}
5.2、验证表达式
/**
* desc: 条件验证,验证表达式
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/15 10:02
*/
public class TerminalExpression extends AbstractExpression {
/**
* 指定字符串
*/
private String data;
public TerminalExpression(String data) {
this.data = data;
}
/**
* 验证表达式是否包含指定字符串
* @param context 表达式
* @return true or false
*/
@Override
public boolean interpret(String context) {
if (context.contains(data)){
return true;
}else {
return false;
}
}
}
5.3、and条件表达式
/**
* desc: and条件表达式
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/15 10:47
*/
public class AndExpression extends AbstractExpression {
private AbstractExpression exp1;
private AbstractExpression exp2;
public AndExpression(AbstractExpression exp1, AbstractExpression exp2) {
this.exp1 = exp1;
this.exp2 = exp2;
}
@Override
public boolean interpret(String context) {
return exp1.interpret(context) && exp2.interpret(context);
}
}
5.4、或条件表达式
/**
* desc: 或条件表达式
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/15 10:45
*/
public class OrExpression extends AbstractExpression {
private AbstractExpression exp1;
private AbstractExpression exp2;
public OrExpression(AbstractExpression exp1, AbstractExpression exp2) {
this.exp1 = exp1;
this.exp2 = exp2;
}
@Override
public boolean interpret(String context) {
return exp1.interpret(context) || exp2.interpret(context);
}
}
5.5、测试
/**
* desc: 测试
*
* @author xuebin3765@163.com
* @version 1.0
* @date 2020/06/15 10:31
*/
public class ClientTest {
// 小明和张三是男性
public static AbstractExpression getMaleExpression(){
AbstractExpression xm = new TerminalExpression("小明");
AbstractExpression zs = new TerminalExpression("张三");
return new OrExpression(xm, zs);
}
//规则:妲己 是一个已婚的女性
public static AbstractExpression getMarredExpression(){
AbstractExpression julie = new TerminalExpression("妲己");
AbstractExpression married = new TerminalExpression("已婚");
return new AndExpression(julie, married);
}
public static void main(String[] args) {
AbstractExpression isMale = getMaleExpression();
AbstractExpression isMarredWoman = getMarredExpression();
System.out.println("小明是男性:" + isMale.interpret("小明"));
System.out.println("李四是男性:" + isMale.interpret("李四"));
System.out.println("妲己是已婚女性:"+ isMarredWoman.interpret("妲己已婚"));
System.out.println("武则天是已婚女性:"+ isMarredWoman.interpret("武则天已婚"));
}
}
5.6、运行结果
小明是男性:true
李四是男性:false
妲己是已婚女性:true
武则天是已婚女性:false