解释器模式案例

wen java案例 3

解释器模式(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));
    }
}

模式总结

优点:

  1. 易于改变和扩展文法:新增表达式类即可扩展功能
  2. 实现文法容易:每个文法规则的实现都在单独的类中
  3. 易于实现简单的语言:适合简单的语法解析

缺点:

  1. 难以维护复杂文法:类数量会大量增加
  2. 执行效率较低:涉及大量的递归调用
  3. 不适合复杂语法:过于复杂的语法会使代码结构混乱

适用场景:

  • 需要解释执行的语言,且语法相对简单
  • 语法规则频繁变化
  • 可以表示为语法树的语言
  • 对效率要求不高的场景

注意事项:

  • 当语法规则较多时,考虑使用其他解析方案(如Antlr)
  • 可以使用Flyweight模式共享终结符表达式
  • 可以结合Visitor模式来遍历抽象语法树

抱歉,评论功能暂时关闭!