解释器模式是一种行为型设计模式,它定义了一种语言的语法,并提供了一个解释器来解释这种语言中的句子。简单来说,它就是用来解析特定语法的一种模式!
当我们需要解析一些特定的语法规则时,解释器模式就派上用场了!比如:
解释器模式主要包含以下几个角色:
+------------------------+
| AbstractExpression |
+------------------------+
| + interpret(context) |
+------------------------+
^
|
|
+---------+-----------+
| |
| |
+-------------------+ +----------------------+
| TerminalExpression | | NonterminalExpression|
+-------------------+ +----------------------+
| + interpret(context) | | + interpret(context) |
+-------------------+ +----------------------+
| - expressions |
+----------------------+
// 抽象表达式
public interface Expression {
boolean interpret(String context);
}
// 终结符表达式
public class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) {
this.data = data;
}
@Override
public boolean interpret(String context) {
if (context.contains(data)) {
return true;
}
return false;
}
}
// 非终结符表达式 - 与操作
public class AndExpression implements Expression {
private Expression expr1;
private Expression expr2;
public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) && expr2.interpret(context);
}
}
// 非终结符表达式 - 或操作
public class OrExpression implements Expression {
private Expression expr1;
private Expression expr2;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Expression isMale = new TerminalExpression("男");
Expression isTall = new TerminalExpression("高");
// 高且男
Expression isTallMale = new AndExpression(isTall, isMale);
System.out.println("高且男: " + isTallMale.interpret("高男"));
System.out.println("高且男: " + isTallMale.interpret("矮男"));
// 高或男
Expression isTallOrMale = new OrExpression(isTall, isMale);
System.out.println("高或男: " + isTallOrMale.interpret("高女"));
System.out.println("高或男: " + isTallOrMale.interpret("矮女"));
}
}
正则表达式引擎是解释器模式的一个典型应用。下面是一个简单的正则表达式引擎的实现:
// 抽象表达式
public interface RegexExpression {
boolean interpret(String context, int position);
}
// 终结符表达式:字符匹配
public class CharacterExpression implements RegexExpression {
private char character;
public CharacterExpression(char character) {
this.character = character;
}
@Override
public boolean interpret(String context, int position) {
if (position < context.length()) {
return context.charAt(position) == character;
}
return false;
}
}
// 终结符表达式:点号匹配任意字符
public class DotExpression implements RegexExpression {
@Override
public boolean interpret(String context, int position) {
if (position < context.length()) {
return true; // 匹配任意字符
}
return false;
}
}
// 非终结符表达式:星号(零次或多次)
public class StarExpression implements RegexExpression {
private RegexExpression expression;
public StarExpression(RegexExpression expression) {
this.expression = expression;
}
@Override
public boolean interpret(String context, int position) {
// 匹配零次
if (position >= context.length()) {
return true;
}
// 匹配一次或多次
int currentPosition = position;
while (currentPosition < context.length() &&
expression.interpret(context, currentPosition)) {
currentPosition++;
}
return true;
}
}
// 客户端代码
public class RegexEngine {
public static boolean match(String regex, String text) {
// 构建正则表达式的解释器
List<RegexExpression> expressions = new ArrayList<>();
for (int i = 0; i < regex.length(); i++) {
char c = regex.charAt(i);
if (c == '.') {
expressions.add(new DotExpression());
} else if (c == '*' && !expressions.isEmpty()) {
RegexExpression prev = expressions.remove(expressions.size() - 1);
expressions.add(new StarExpression(prev));
} else {
expressions.add(new CharacterExpression(c));
}
}
// 解释
int position = 0;
for (RegexExpression exp : expressions) {
if (!exp.interpret(text, position)) {
return false;
}
position++;
}
return position == text.length();
}
}
这个简单的正则表达式引擎展示了解释器模式的强大之处!我们可以通过组合不同的表达式,构建复杂的正则表达式解释器!✨
在数据库系统中,SQL解析器就是解释器模式的一个典型应用。它将SQL语句解析成抽象语法树,然后执行相应的操作:
// 抽象表达式
public interface SQLExpression {
void interpret(SQLContext context);
}
// 上下文
public class SQLContext {
private Map<String, List<Map<String, Object>>> tables = new HashMap<>();
private List<Map<String, Object>> result;
public void setTable(String name, List<Map<String, Object>> data) {
tables.put(name, data);
}
public List<Map<String, Object>> getTable(String name) {
return tables.get(name);
}
public void setResult(List<Map<String, Object>> result) {
this.result = result;
}
public List<Map<String, Object>> getResult() {
return result;
}
}
// 终结符表达式:FROM子句
public class FromExpression implements SQLExpression {
private String tableName;
public FromExpression(String tableName) {
this.tableName = tableName;
}
@Override
public void interpret(SQLContext context) {
context.setResult(context.getTable(tableName));
}
}
// 非终结符表达式:SELECT子句
public class SelectExpression implements SQLExpression {
private List<String> columns;
public SelectExpression(List<String> columns) {
this.columns = columns;
}
@Override
public void interpret(SQLContext context) {
List<Map<String, Object>> result = context.getResult();
List<Map<String, Object>> newResult = new ArrayList<>();
for (Map<String, Object> row : result) {
Map<String, Object> newRow = new HashMap<>();
for (String column : columns) {
if (row.containsKey(column)) {
newRow.put(column, row.get(column));
}
}
newResult.add(newRow);
}
context.setResult(newResult);
}
}
// 非终结符表达式:WHERE子句
public class WhereExpression implements SQLExpression {
private String column;
private String value;
public WhereExpression(String column, String value) {
this.column = column;
this.value = value;
}
@Override
public void interpret(SQLContext context) {
List<Map<String, Object>> result = context.getResult();
List<Map<String, Object>> newResult = new ArrayList<>();
for (Map<String, Object> row : result) {
if (row.containsKey(column) && row.get(column).equals(value)) {
newResult.add(row);
}
}
context.setResult(newResult);
}
}
// 客户端代码
public class SQLParser {
public static void main(String[] args) {
// 准备数据
SQLContext context = new SQLContext();
List<Map<String, Object>> users = new ArrayList<>();
Map<String, Object> user1 = new HashMap<>();
user1.put("id", 1);
user1.put("name", "宝子1");
user1.put("age", 25);
Map<String, Object> user2 = new HashMap<>();
user2.put("id", 2);
user2.put("name", "宝子2");
user2.put("age", 30);
users.add(user1);
users.add(user2);
context.setTable("users", users);
// 构建SQL表达式:SELECT id, name FROM users WHERE age = 25
FromExpression from = new FromExpression("users");
WhereExpression where = new WhereExpression("age", "25");
SelectExpression select = new SelectExpression(Arrays.asList("id", "name"));
// 执行SQL
from.interpret(context);
where.interpret(context);
select.interpret(context);
// 输出结果
List<Map<String, Object>> result = context.getResult();
for (Map<String, Object> row : result) {
System.out.println(row);
}
// 输出:{id=1, name=宝子1}
}
}
这个例子展示了如何使用解释器模式实现一个简单的SQL解析器,它可以解析和执行简单的SQL查询语句!️✨
Java的java.util.regex.Pattern
类使用了解释器模式。当我们编译一个正则表达式时,它会被解析成一个语法树,然后用于匹配字符串:
Pattern pattern = Pattern.compile("a*b"); // 编译正则表达式
Matcher matcher = pattern.matcher("aaaab"); // 创建匹配器
boolean matches = matcher.matches(); // 进行匹配
System.out.println(matches); // 输出:true
Java的java.text.Format
类及其子类(如SimpleDateFormat
、NumberFormat
等)也使用了解释器模式的思想,它们解析格式化字符串,并根据这些字符串对数据进行格式化:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
String formattedDate = format.format(date);
System.out.println(formattedDate); // 输出:2023-05-20 15:30:45
Java的表达式引擎,如Spring Expression Language (SpEL)和Java Expression Language (EL),也使用了解释器模式:
// Spring Expression Language (SpEL)
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello, ' + name");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("name", "宝子");
String message = (String) exp.getValue(context);
System.out.println(message); // 输出:Hello, 宝子
解释器模式是一种强大的设计模式,它让我们可以为特定领域创建一种简单的语言,并提供一种解释这种语言的方法。它特别适合处理简单的、重复出现的问题,可以将这些问题表达为一种语言,然后通过解释器来解决。
在实际开发中,当你需要为用户提供一种定制规则或表达式的能力时,解释器模式是一个非常好的选择!记住,好的设计模式就像好的工具一样,用在对的地方才能发挥最大的作用!
希望这篇文章对你理解解释器模式有所帮助!如果有任何问题,欢迎在评论区留言讨论!