模式定义

解释器模式是一种行为型设计模式,它给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。解释器模式是一种按照规定语法进行解析的方案,在现在项目中使用较少。它提供了评估语言的语法或表达式的方式,实现了文法表达式处理的接口,该接口解释一个特定的上下文。

模式结构

graph TD A[AbstractExpression] --> B[TerminalExpression] A --> C[NonTerminalExpression] C --> D[Context]

实现方式

基础实现

定义抽象表达式接口,实现终结符表达式和非终结符表达式类。

// 上下文类
class Context {
    private String input;
    private int output;
    
    public Context(String input) {
        this.input = input;
    }
    
    public String getInput() {
        return input;
    }
    
    public void setInput(String input) {
        this.input = input;
    }
    
    public int getOutput() {
        return output;
    }
    
    public void setOutput(int output) {
        this.output = output;
    }
}

// 抽象表达式接口
interface Expression {
    void interpret(Context context);
}

// 终结符表达式 - 数字
class NumberExpression implements Expression {
    private int number;
    
    public NumberExpression(int number) {
        this.number = number;
    }
    
    public NumberExpression(String number) {
        this.number = Integer.parseInt(number);
    }
    
    @Override
    public void interpret(Context context) {
        context.setOutput(number);
    }
}

// 非终结符表达式 - 加法
class AddExpression implements Expression {
    private Expression leftExpression;
    private Expression rightExpression;
    
    public AddExpression(Expression left, Expression right) {
        this.leftExpression = left;
        this.rightExpression = right;
    }
    
    @Override
    public void interpret(Context context) {
        // 解释左表达式
        leftExpression.interpret(context);
        int leftResult = context.getOutput();
        
        // 解释右表达式
        rightExpression.interpret(context);
        int rightResult = context.getOutput();
        
        // 执行加法运算
        context.setOutput(leftResult + rightResult);
    }
}

// 非终结符表达式 - 减法
class SubtractExpression implements Expression {
    private Expression leftExpression;
    private Expression rightExpression;
    
    public SubtractExpression(Expression left, Expression right) {
        this.leftExpression = left;
        this.rightExpression = right;
    }
    
    @Override
    public void interpret(Context context) {
        // 解释左表达式
        leftExpression.interpret(context);
        int leftResult = context.getOutput();
        
        // 解释右表达式
        rightExpression.interpret(context);
        int rightResult = context.getOutput();
        
        // 执行减法运算
        context.setOutput(leftResult - rightResult);
    }
}

// 表达式解析器
class ExpressionParser {
    private Stack stack = new Stack<>();
    
    public Expression parse(String expression) {
        String[] tokens = expression.split(" ");
        
        for (String token : tokens) {
            if (isOperator(token)) {
                // 弹出右操作数和左操作数
                Expression right = stack.pop();
                Expression left = stack.pop();
                
                // 创建相应的操作表达式
                Expression operator = createOperator(token, left, right);
                stack.push(operator);
            } else {
                // 数字,创建数字表达式
                stack.push(new NumberExpression(token));
            }
        }
        
        // 最终结果是栈中唯一的表达式
        return stack.pop();
    }
    
    private boolean isOperator(String token) {
        return token.equals("+") || token.equals("-");
    }
    
    private Expression createOperator(String operator, Expression left, Expression right) {
        switch (operator) {
            case "+":
                return new AddExpression(left, right);
            case "-":
                return new SubtractExpression(left, right);
            default:
                throw new IllegalArgumentException("不支持的操作符: " + operator);
        }
    }
}

使用示例

public class InterpreterPatternDemo {
    public static void main(String[] args) {
        // 创建表达式解析器
        ExpressionParser parser = new ExpressionParser();
        
        // 解析并计算表达式: 10 + 5 - 3
        String expression = "10 5 + 3 -";
        Expression expr = parser.parse(expression);
        
        Context context = new Context(expression);
        expr.interpret(context);
        
        System.out.println("表达式 '" + expression + "' 的结果是: " + context.getOutput());
        
        // 解析并计算表达式: 20 10 - 5 +
        expression = "20 10 - 5 +";
        expr = parser.parse(expression);
        context = new Context(expression);
        expr.interpret(context);
        
        System.out.println("表达式 '" + expression + "' 的结果是: " + context.getOutput());
    }
}

经典案例

1. 正则表达式引擎

正则表达式引擎是解释器模式的一个复杂应用:

// 抽象表达式
abstract class RegexExpression {
    public abstract boolean interpret(String context);
}

// 终结符表达式 - 字面量
class LiteralExpression extends RegexExpression {
    private String literal;
    
    public LiteralExpression(String literal) {
        this.literal = literal;
    }
    
    @Override
    public boolean interpret(String context) {
        return context.contains(literal);
    }
}

// 终结符表达式 - 数字
class DigitExpression extends RegexExpression {
    @Override
    public boolean interpret(String context) {
        return context.matches(".*\\d.*");
    }
}

// 非终结符表达式 - 或操作
class OrExpression extends RegexExpression {
    private RegexExpression expression1;
    private RegexExpression expression2;
    
    public OrExpression(RegexExpression expression1, RegexExpression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }
    
    @Override
    public boolean interpret(String context) {
        return expression1.interpret(context) || expression2.interpret(context);
    }
}

// 非终结符表达式 - 与操作
class AndExpression extends RegexExpression {
    private RegexExpression expression1;
    private RegexExpression expression2;
    
    public AndExpression(RegexExpression expression1, RegexExpression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }
    
    @Override
    public boolean interpret(String context) {
        return expression1.interpret(context) && expression2.interpret(context);
    }
}

// 正则表达式构建器
class RegexBuilder {
    // 创建"张"或"李"的表达式
    public static RegexExpression createNamePattern() {
        RegexExpression zhang = new LiteralExpression("张");
        RegexExpression li = new LiteralExpression("李");
        return new OrExpression(zhang, li);
    }
    
    // 创建包含数字的表达式
    public static RegexExpression createDigitPattern() {
        return new DigitExpression();
    }
    
    // 创建姓名且包含数字的表达式
    public static RegexExpression createNameWithDigitPattern() {
        RegexExpression name = createNamePattern();
        RegexExpression digit = createDigitPattern();
        return new AndExpression(name, digit);
    }
}

// 使用示例
public class RegexInterpreterDemo {
    public static void main(String[] args) {
        RegexExpression namePattern = RegexBuilder.createNamePattern();
        RegexExpression digitPattern = RegexBuilder.createDigitPattern();
        RegexExpression nameWithDigitPattern = RegexBuilder.createNameWithDigitPattern();
        
        String[] testStrings = {
            "张三",
            "李四",
            "王五",
            "张三123",
            "李四456",
            "王五789",
            "123456"
        };
        
        System.out.println("=== 姓名模式测试 (张或李) ===");
        for (String str : testStrings) {
            System.out.println("'" + str + "' 匹配姓名模式: " + namePattern.interpret(str));
        }
        
        System.out.println("\n=== 数字模式测试 ===");
        for (String str : testStrings) {
            System.out.println("'" + str + "' 匹配数字模式: " + digitPattern.interpret(str));
        }
        
        System.out.println("\n=== 姓名且包含数字模式测试 ===");
        for (String str : testStrings) {
            System.out.println("'" + str + "' 匹配姓名且包含数字模式: " + nameWithDigitPattern.interpret(str));
        }
    }
}

2. 布尔表达式解释器

布尔表达式的解析和计算也是解释器模式的应用:

// 上下文类
class BooleanContext {
    private Map variables = new HashMap<>();
    
    public void setVariable(String name, Boolean value) {
        variables.put(name, value);
    }
    
    public Boolean getVariable(String name) {
        return variables.get(name);
    }
    
    public Set getVariableNames() {
        return variables.keySet();
    }
}

// 抽象表达式
abstract class BooleanExpression {
    public abstract boolean interpret(BooleanContext context);
}

// 终结符表达式 - 变量
class VariableExpression extends BooleanExpression {
    private String name;
    
    public VariableExpression(String name) {
        this.name = name;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        Boolean value = context.getVariable(name);
        return value != null ? value : false;
    }
}

// 终结符表达式 - 常量
class ConstantExpression extends BooleanExpression {
    private boolean value;
    
    public ConstantExpression(boolean value) {
        this.value = value;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        return value;
    }
}

// 非终结符表达式 - 与操作
class AndExpression extends BooleanExpression {
    private BooleanExpression left;
    private BooleanExpression right;
    
    public AndExpression(BooleanExpression left, BooleanExpression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        return left.interpret(context) && right.interpret(context);
    }
}

// 非终结符表达式 - 或操作
class OrExpression extends BooleanExpression {
    private BooleanExpression left;
    private BooleanExpression right;
    
    public OrExpression(BooleanExpression left, BooleanExpression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        return left.interpret(context) || right.interpret(context);
    }
}

// 非终结符表达式 - 非操作
class NotExpression extends BooleanExpression {
    private BooleanExpression expression;
    
    public NotExpression(BooleanExpression expression) {
        this.expression = expression;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        return !expression.interpret(context);
    }
}

// 布尔表达式解析器
class BooleanExpressionParser {
    public BooleanExpression parse(String expression) {
        // 简单的解析器实现,仅支持基本的布尔表达式
        // 实际应用中需要更复杂的词法和语法分析
        
        // 移除空格
        expression = expression.replaceAll("\\s+", "");
        
        // 处理非操作
        if (expression.startsWith("!")) {
            BooleanExpression operand = parse(expression.substring(1));
            return new NotExpression(operand);
        }
        
        // 处理括号
        if (expression.startsWith("(") && expression.endsWith(")")) {
            // 简化处理,实际需要考虑嵌套括号
            return parse(expression.substring(1, expression.length() - 1));
        }
        
        // 处理与操作
        int andIndex = expression.indexOf("&&");
        if (andIndex != -1) {
            BooleanExpression left = parse(expression.substring(0, andIndex));
            BooleanExpression right = parse(expression.substring(andIndex + 2));
            return new AndExpression(left, right);
        }
        
        // 处理或操作
        int orIndex = expression.indexOf("||");
        if (orIndex != -1) {
            BooleanExpression left = parse(expression.substring(0, orIndex));
            BooleanExpression right = parse(expression.substring(orIndex + 2));
            return new OrExpression(left, right);
        }
        
        // 处理常量
        if (expression.equals("true")) {
            return new ConstantExpression(true);
        }
        if (expression.equals("false")) {
            return new ConstantExpression(false);
        }
        
        // 默认为变量
        return new VariableExpression(expression);
    }
}

// 使用示例
public class BooleanInterpreterDemo {
    public static void main(String[] args) {
        // 创建表达式解析器
        BooleanExpressionParser parser = new BooleanExpressionParser();
        
        // 解析布尔表达式: a && (b || c)
        String expressionStr = "a&&(b||c)";
        BooleanExpression expression = parser.parse(expressionStr);
        
        // 创建上下文并设置变量值
        BooleanContext context = new BooleanContext();
        context.setVariable("a", true);
        context.setVariable("b", false);
        context.setVariable("c", true);
        
        // 解释表达式
        boolean result = expression.interpret(context);
        System.out.println("表达式 '" + expressionStr + "' 的结果: " + result);
        
        // 测试不同的变量值
        context.setVariable("a", false);
        result = expression.interpret(context);
        System.out.println("当 a=false, b=false, c=true 时,表达式 '" + expressionStr + "' 的结果: " + result);
        
        // 解析更复杂的表达式: (a || b) && !c
        expressionStr = "(a||b)&&!c";
        expression = parser.parse(expressionStr);
        
        context.setVariable("a", true);
        context.setVariable("b", false);
        context.setVariable("c", false);
        
        result = expression.interpret(context);
        System.out.println("表达式 '" + expressionStr + "' 的结果: " + result);
    }
}

应用场景

优缺点

优点

  • 可扩展性好:在语法树中增加新的节点类非常方便,符合开闭原则
  • 容易实现:对于简单的文法,实现起来相对容易
  • 灵活性强:可以方便地改变和扩展文法
  • 易于维护:每条语法规则都可以单独维护

缺点

  • 执行效率较低:大量使用循环和递归调用,性能一般
  • 复杂度高:对于复杂的文法,类的设计比较困难
  • 适用场景有限:只在特定的场景下使用,适用范围不广
  • 增加系统复杂性:引入大量类,增加系统复杂性