1 Interpreter Pattern 解释器模式
目的:对于一个使用规定格式和语法的代码,可以建立一个解释器来解释该语言中的句子;
实现:构件语法树,定义终结符与非终结符。
1.对于一些固定文法构建一个解释句子的解释器,也就是翻译成你能懂的东西;
2.高效的解释器通常不是通过直接解释抽象语法树来实现的,而是需要将它们转换成其他形式,使用解释器模式的执行效率并不高;
3.解释器模式在正则表达式、XML 文档解释等领域还是得到了广泛使用。
2 实现
代码场景:将依据sql解释成白话文。
1. sql是要被解释的脚本
2. 各个解释器是表达式角色
2.1 代码实现
环境类角色:上下文Context类
/**
* 全局性作用 存储一些全局性的数据
*/
public class Context {
private String sql;
public Context(String sql) {
this.sql = sql;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
}
抽象表达式角色:AbstractExpression类
public abstract class AbstractExpression {
// 入参为 全局性上下文
public abstract void interpret(Context ctx);
}
非终结符表达式角色:特殊符号解释器EspecialExpression类
/**
* 特殊符号解释器
*/
public class EspecialExpression extends AbstractExpression {
private Map<String, String> map = new HashMap<String, String>();
public EspecialExpression() {
map.put("*", "所有字段");
map.put("=", "等于");
}
@Override
public void interpret(Context ctx) {
String sql = ctx.getSql();
if (sql.contains("=")) {
sql = sql.replaceAll("'", "");
}
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String next = iterator.next();
if (sql.contains(next)) {
sql = sql.replace(next, map.get(next));
}
}
ctx.setSql(sql);
AbstractExpression keExp = new KeywordExpression();
keExp.interpret(ctx);
}
}
非终结符表达式角色:关键字号解释器KeywordExpression类
/**
* 关键字解释器
*/
public class KeywordExpression extends AbstractExpression {
private Map<String, String> map = new HashMap<String, String>();
public KeywordExpression() {
map.put("select", "查询");
map.put("from", "从表");
map.put("where", "中,条件是");
}
@Override
public void interpret(Context ctx) {
String sql = ctx.getSql();
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
String next = iterator.next();
if (sql.contains(next)) {
sql = sql.replace(next, map.get(next));
}
}
ctx.setSql(sql);
AbstractExpression keExp = new EndExpression();
keExp.interpret(ctx);
}
}
终结符表达式角色:EndExpression类
/**
* 终结符解释器
*/
public class EndExpression extends AbstractExpression {
@Override
public void interpret(Context ctx) {
String sql = ctx.getSql();
sql = sql.replace(";", "");
ctx.setSql(sql);
}
}
2.2 涉及角色
在解释器模式结构图中包含如下几个角色:
(1)AbstractExpression(抽象表达式):在抽象表达式中声明了抽象的解释操作,它是所有终结符表达式和非终结符表达式的公共父类。
(2)TerminalExpression(终结符表达式):终结符表达式是抽象表达式的子类,它实现了与文法中的终结符相关联的解释操作,在句子中的每一个终结符都是该类的一个实例。通常在一个解释器模式中只有少数几个终结符表达式类,它们的实例可以通过非终结符表达式组成较为复杂的句子。
(3)NonterminalExpression(非终结符表达式):非终结符表达式也是抽象表达式的子类,它实现了文法中非终结符的解释操作,由于在非终结符表达式中可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释操作一般通过递归的方式来完成。
(4)Context(环境类):环境类又称为上下文类,它用于存储解释器之外的一些全局信息,通常它临时存储了需要解释的语句。
环境类 Context 用于存储解释器之外的一些全局信息,它通常作为参数被传递到所有表达式的解释方法 interpret() 中,可以在 Context 对象中存储和访问表达式解释器的状态,向表达式解释器提供一些全局的、公共的数据,此外还可以在 Context 中增加一些所有表达式解释器都共有的功能,减轻解释器的职责。
2.3 调用
调用者:
public class Client {
public static void main(String[] args) {
// 要解析的sql
String sql = "select * from students where name = 'weixx';";
System.out.println("解析前---->" + sql);
// 生成上下文
Context ctx = new Context(sql);
// 先开始特殊字符解释器
AbstractExpression eExp = new EspecialExpression();
eExp.interpret(ctx);
System.out.println("解析后---->" + ctx.getSql());
}
}
结果:
解析前---->select * from students where name = 'weixx';
解析后---->查询 所有字段 从表 students 中,条件是 name 等于 weixx
参考文献:
[ 1 ] 图解设计模式/(日)结城浩著;杨文轩译。–北京:人民邮电出版社,2017.1.
[ 2 ] 维基百科 设计模式
[ 3 ] 极客学院WIKI–设计模式.
[ 4 ] 菜鸟教程–设计模式.