解释器模式(Interpreter Pattern)案例详解
模式概述
解释器模式定义了一个语言的文法,并建立一个解释器来解释该语言中的句子,它属于行为型模式,适用于需要解释特定语法的场景。

案例一:数学表达式解释器
这是一个最经典的案例,用于解释和计算简单的数学表达式。
// 抽象表达式
interface Expression {
int interpret();
}
// 终结符表达式 - 数字
class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret() {
return number;
}
}
// 非终结符表达式 - 加法
class AddExpression implements Expression {
private Expression left;
private Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() + right.interpret();
}
}
// 非终结符表达式 - 减法
class SubtractExpression implements Expression {
private Expression left;
private Expression right;
public SubtractExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() - right.interpret();
}
}
// 非终结符表达式 - 乘法
class MultiplyExpression implements Expression {
private Expression left;
private Expression right;
public MultiplyExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() * right.interpret();
}
}
// 非终结符表达式 - 除法
class DivideExpression implements Expression {
private Expression left;
private Expression right;
public DivideExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
int divisor = right.interpret();
if (divisor == 0) {
throw new ArithmeticException("除数不能为0");
}
return left.interpret() / divisor;
}
}
// 客户端测试类
public class ExpressionDemo {
public static void main(String[] args) {
// 构建表达式: (10 + 20) * 3 - 5
Expression expression = new SubtractExpression(
new MultiplyExpression(
new AddExpression(
new NumberExpression(10),
new NumberExpression(20)
),
new NumberExpression(3)
),
new NumberExpression(5)
);
int result = expression.interpret();
System.out.println("(10 + 20) * 3 - 5 = " + result); // 输出: 85
}
}
案例二:SQL查询解释器
这是一个更复杂的实际应用案例,模拟简单的SQL查询解析。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// 上下文 - 存储数据
class QueryContext {
private List<Map<String, String>> data;
private Map<String, String> params;
public QueryContext() {
this.data = new ArrayList<>();
this.params = new HashMap<>();
}
public void addRow(Map<String, String> row) {
data.add(row);
}
public void addParams(Map<String, String> params) {
this.params.putAll(params);
}
public List<Map<String, String>> getData() {
return data;
}
public String getValue(Map<String, String> row, String column) {
String value = row.get(column);
if (value == null && params.containsKey(column)) {
return params.get(column);
}
return value;
}
}
// 抽象表达式
interface QueryExpression {
List<Map<String, String>> interpret(QueryContext context);
}
// 终结符表达式 - 选择操作
class SelectExpression implements QueryExpression {
private String table;
private WhereExpression where;
public SelectExpression(String table, WhereExpression where) {
this.table = table;
this.where = where;
}
@Override
public List<Map<String, String>> interpret(QueryContext context) {
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, String> row : context.getData()) {
if (where == null || where.interpret(context, row)) {
result.add(row);
}
}
return result;
}
}
// 条件表达式 - 用于WHERE子句
interface WhereExpression {
boolean interpret(QueryContext context, Map<String, String> row);
}
// 等于条件
class EqualsExpression implements WhereExpression {
private String column;
private String value;
public EqualsExpression(String column, String value) {
this.column = column;
this.value = value;
}
@Override
public boolean interpret(QueryContext context, Map<String, String> row) {
String actualValue = context.getValue(row, column);
return value.equals(actualValue);
}
}
// 不等于条件
class NotEqualsExpression implements WhereExpression {
private String column;
private String value;
public NotEqualsExpression(String column, String value) {
this.column = column;
this.value = value;
}
@Override
public boolean interpret(QueryContext context, Map<String, String> row) {
String actualValue = context.getValue(row, column);
return !value.equals(actualValue);
}
}
// AND条件
class AndExpression implements WhereExpression {
private WhereExpression left;
private WhereExpression right;
public AndExpression(WhereExpression left, WhereExpression right) {
this.left = left;
this.right = right;
}
@Override
public boolean interpret(QueryContext context, Map<String, String> row) {
return left.interpret(context, row) && right.interpret(context, row);
}
}
// OR条件
class OrExpression implements WhereExpression {
private WhereExpression left;
private WhereExpression right;
public OrExpression(WhereExpression left, WhereExpression right) {
this.left = left;
this.right = right;
}
@Override
public boolean interpret(QueryContext context, Map<String, String> row) {
return left.interpret(context, row) || right.interpret(context, row);
}
}
// 客户端测试
public class SQLQueryDemo {
public static void main(String[] args) {
// 准备测试数据
QueryContext context = new QueryContext();
Map<String, String> row1 = new HashMap<>();
row1.put("name", "张三");
row1.put("age", "25");
row1.put("city", "北京");
context.addRow(row1);
Map<String, String> row2 = new HashMap<>();
row2.put("name", "李四");
row2.put("age", "30");
row2.put("city", "上海");
context.addRow(row2);
Map<String, String> row3 = new HashMap<>();
row3.put("name", "王五");
row3.put("age", "25");
row3.put("city", "北京");
context.addRow(row3);
// 构建查询: SELECT * FROM users WHERE age = 25 AND city = '北京'
WhereExpression where = new AndExpression(
new EqualsExpression("age", "25"),
new EqualsExpression("city", "北京")
);
SelectExpression select = new SelectExpression("users", where);
List<Map<String, String>> result = select.interpret(context);
System.out.println("查询结果:");
for (Map<String, String> row : result) {
System.out.println("姓名: " + row.get("name") +
", 年龄: " + row.get("age") +
", 城市: " + row.get("city"));
}
}
}
案例三:日期格式解释器
import java.text.SimpleDateFormat;
import java.util.Date;
// 日期上下文
class DateContext {
private String dateStr;
private String format;
public DateContext(String dateStr, String format) {
this.dateStr = dateStr;
this.format = format;
}
public String getDateStr() {
return dateStr;
}
public String getFormat() {
return format;
}
}
// 抽象表达式
interface DateExpression {
String interpret(DateContext context);
}
// 年月日解析
class YearMonthDayExpression implements DateExpression {
@Override
public String interpret(DateContext context) {
String dateStr = context.getDateStr();
String year = dateStr.substring(0, 4);
String month = dateStr.substring(4, 6);
String day = dateStr.substring(6, 8);
String format = context.getFormat();
format = format.replace("YYYY", year);
format = format.replace("MM", month);
format = format.replace("DD", day);
return format;
}
}
// 时间解析
class TimeExpression implements DateExpression {
@Override
public String interpret(DateContext context) {
String dateStr = context.getDateStr();
if (dateStr.length() >= 14) {
String hour = dateStr.substring(8, 10);
String minute = dateStr.substring(10, 12);
String second = dateStr.substring(12, 14);
String format = context.getFormat();
format = format.replace("HH", hour);
format = format.replace("mm", minute);
format = format.replace("SS", second);
return format;
}
return context.getFormat();
}
}
// 完整日期解释器
class CompleteDateExpression implements DateExpression {
private YearMonthDayExpression datePart;
private TimeExpression timePart;
public CompleteDateExpression() {
this.datePart = new YearMonthDayExpression();
this.timePart = new TimeExpression();
}
@Override
public String interpret(DateContext context) {
String datePartResult = datePart.interpret(context);
String timePartResult = timePart.interpret(context);
StringBuilder result = new StringBuilder();
if (context.getFormat().contains("YYYY")) {
result.append(datePartResult);
}
if (context.getFormat().contains("HH")) {
if (result.length() > 0) {
result.append(" ");
}
result.append(timePartResult.split(" ")[0]);
}
return result.toString();
}
}
// 客户端测试
public class DateExpressionDemo {
public static void main(String[] args) {
String dateStr = "20240115143025"; // 2024年1月15日 14:30:25
// 格式1:年月日
DateContext context1 = new DateContext(dateStr, "YYYY-MM-DD");
DateExpression expression1 = new YearMonthDayExpression();
System.out.println("日期格式1: " + expression1.interpret(context1));
// 格式2:带时间
DateContext context2 = new DateContext(dateStr, "YYYY/MM/DD HH:mm:SS");
DateExpression expression2 = new CompleteDateExpression();
System.out.println("日期格式2: " + expression2.interpret(context2));
}
}
模式总结
优点:
- 易于改变和扩展文法:新增表达式类即可扩展功能
- 实现文法容易:每个文法规则的实现都在单独的类中
- 易于实现简单的语言:适合简单的语法解析
缺点:
- 难以维护复杂文法:类数量会大量增加
- 执行效率较低:涉及大量的递归调用
- 不适合复杂语法:过于复杂的语法会使代码结构混乱
适用场景:
- 需要解释执行的语言,且语法相对简单
- 语法规则频繁变化
- 可以表示为语法树的语言
- 对效率要求不高的场景
注意事项:
- 当语法规则较多时,考虑使用其他解析方案(如Antlr)
- 可以使用Flyweight模式共享终结符表达式
- 可以结合Visitor模式来遍历抽象语法树
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播