解释器模式 (Interpreter Pattern)

概述 (Overview)

解释器模式是一种行为型设计模式,它定义了一种语言的文法表示,并定义了一个解释器,该解释器使用该表示来解释语言中的句子。

Interpreter Pattern is a behavioral design pattern that defines a grammatical representation for a language and provides an interpreter to interpret sentences in the language.

意图 (Intent)

给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

适用场景 (When to Use)

  • 当需要解释一个语言时,可以将该语言中的句子表示为一个抽象语法树
  • 当语言的文法比较简单时
  • 当效率不是关键问题时
  • 当需要处理简单的脚本语言或表达式时
  • 当需要实现简单的规则引擎时
  • 当需要解析配置文件或数据格式时

结构 (Structure)

基础解释器模式结构图 (Basic Interpreter Pattern Structure)

uses
uses
Context
+input: String
+output: String
«interface»
AbstractExpression
+interpret(context: Context)
TerminalExpression
-data: String
+interpret(context: Context)
NonterminalExpression
-expression: AbstractExpression
+interpret(context: Context)
Client
+execute()

实现方式 (Implementation Approaches)

1. 数学表达式解释器 (Mathematical Expression Interpreter)

// 上下文类 - Context Class
public class MathContext {
    private Map<String, Integer> variables = new HashMap<>();
    
    public void setVariable(String name, int value) {
        variables.put(name, value);
    }
    
    public int getVariable(String name) {
        return variables.getOrDefault(name, 0);
    }
}

// 抽象表达式 - Abstract Expression
public interface Expression {
    int interpret(MathContext context);
    String toString();
}

// 终结符表达式 - Terminal Expression
public class NumberExpression implements Expression {
    private int number;
    
    public NumberExpression(int number) {
        this.number = number;
    }
    
    @Override
    public int interpret(MathContext context) {
        return number;
    }
    
    @Override
    public String toString() {
        return String.valueOf(number);
    }
}

public class VariableExpression implements Expression {
    private String name;
    
    public VariableExpression(String name) {
        this.name = name;
    }
    
    @Override
    public int interpret(MathContext context) {
        return context.getVariable(name);
    }
    
    @Override
    public String toString() {
        return name;
    }
}

// 非终结符表达式 - Non-terminal Expression
public class AddExpression implements Expression {
    private Expression leftExpression;
    private Expression rightExpression;
    
    public AddExpression(Expression leftExpression, Expression rightExpression) {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }
    
    @Override
    public int interpret(MathContext context) {
        return leftExpression.interpret(context) + rightExpression.interpret(context);
    }
    
    @Override
    public String toString() {
        return "(" + leftExpression + " + " + rightExpression + ")";
    }
}

public class SubtractExpression implements Expression {
    private Expression leftExpression;
    private Expression rightExpression;
    
    public SubtractExpression(Expression leftExpression, Expression rightExpression) {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }
    
    @Override
    public int interpret(MathContext context) {
        return leftExpression.interpret(context) - rightExpression.interpret(context);
    }
    
    @Override
    public String toString() {
        return "(" + leftExpression + " - " + rightExpression + ")";
    }
}

public class MultiplyExpression implements Expression {
    private Expression leftExpression;
    private Expression rightExpression;
    
    public MultiplyExpression(Expression leftExpression, Expression rightExpression) {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }
    
    @Override
    public int interpret(MathContext context) {
        return leftExpression.interpret(context) * rightExpression.interpret(context);
    }
    
    @Override
    public String toString() {
        return "(" + leftExpression + " * " + rightExpression + ")";
    }
}

public class DivideExpression implements Expression {
    private Expression leftExpression;
    private Expression rightExpression;
    
    public DivideExpression(Expression leftExpression, Expression rightExpression) {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }
    
    @Override
    public int interpret(MathContext context) {
        int rightValue = rightExpression.interpret(context);
        if (rightValue == 0) {
            throw new ArithmeticException("除零错误");
        }
        return leftExpression.interpret(context) / rightValue;
    }
    
    @Override
    public String toString() {
        return "(" + leftExpression + " / " + rightExpression + ")";
    }
}

// 解析器 - Parser
public class MathExpressionParser {
    private String expression;
    private int index;
    
    public MathExpressionParser(String expression) {
        this.expression = expression.replaceAll("\\s+", "");
        this.index = 0;
    }
    
    public Expression parse() {
        return parseExpression();
    }
    
    private Expression parseExpression() {
        Expression left = parseTerm();
        
        while (index < expression.length()) {
            char operator = expression.charAt(index);
            if (operator == '+' || operator == '-') {
                index++;
                Expression right = parseTerm();
                if (operator == '+') {
                    left = new AddExpression(left, right);
                } else {
                    left = new SubtractExpression(left, right);
                }
            } else {
                break;
            }
        }
        
        return left;
    }
    
    private Expression parseTerm() {
        Expression left = parseFactor();
        
        while (index < expression.length()) {
            char operator = expression.charAt(index);
            if (operator == '*' || operator == '/') {
                index++;
                Expression right = parseFactor();
                if (operator == '*') {
                    left = new MultiplyExpression(left, right);
                } else {
                    left = new DivideExpression(left, right);
                }
            } else {
                break;
            }
        }
        
        return left;
    }
    
    private Expression parseFactor() {
        if (index >= expression.length()) {
            throw new IllegalArgumentException("意外的表达式结束");
        }
        
        char ch = expression.charAt(index);
        
        if (ch == '(') {
            index++;
            Expression expr = parseExpression();
            if (index >= expression.length() || expression.charAt(index) != ')') {
                throw new IllegalArgumentException("缺少右括号");
            }
            index++;
            return expr;
        }
        
        if (Character.isDigit(ch)) {
            return parseNumber();
        }
        
        if (Character.isLetter(ch)) {
            return parseVariable();
        }
        
        throw new IllegalArgumentException("意外的字符: " + ch);
    }
    
    private Expression parseNumber() {
        StringBuilder number = new StringBuilder();
        while (index < expression.length() && Character.isDigit(expression.charAt(index))) {
            number.append(expression.charAt(index));
            index++;
        }
        return new NumberExpression(Integer.parseInt(number.toString()));
    }
    
    private Expression parseVariable() {
        StringBuilder variable = new StringBuilder();
        while (index < expression.length() && Character.isLetterOrDigit(expression.charAt(index))) {
            variable.append(expression.charAt(index));
            index++;
        }
        return new VariableExpression(variable.toString());
    }
}

// 客户端使用 - Client Usage
public class MathExpressionDemo {
    public static void main(String[] args) {
        System.out.println("=== 数学表达式解释器模式演示 ===");
        
        MathContext context = new MathContext();
        context.setVariable("x", 10);
        context.setVariable("y", 5);
        context.setVariable("z", 2);
        
        // 测试不同的表达式
        String[] expressions = {
            "3 + 5",
            "10 - 3",
            "4 * 6",
            "15 / 3",
            "x + y",
            "x * y + z",
            "(x + y) * z",
            "x + y * z",
            "((x + y) * z) / 2"
        };
        
        for (String expr : expressions) {
            System.out.println("\n--- 表达式: " + expr + " ---");
            try {
                MathExpressionParser parser = new MathExpressionParser(expr);
                Expression expression = parser.parse();
                
                System.out.println("解析后的表达式: " + expression);
                int result = expression.interpret(context);
                System.out.println("计算结果: " + result);
                
            } catch (Exception e) {
                System.out.println("错误: " + e.getMessage());
            }
        }
        
        System.out.println("\n=== 演示完成 ===");
    }
}

2. 布尔表达式解释器 (Boolean Expression Interpreter)

// 上下文类 - Context Class
public class BooleanContext {
    private Map<String, Boolean> variables = new HashMap<>();
    
    public void setVariable(String name, boolean value) {
        variables.put(name, value);
    }
    
    public boolean getVariable(String name) {
        return variables.getOrDefault(name, false);
    }
}

// 抽象表达式 - Abstract Expression
public interface BooleanExpression {
    boolean interpret(BooleanContext context);
    String toString();
}

// 终结符表达式 - Terminal Expression
public class BooleanVariableExpression implements BooleanExpression {
    private String name;
    
    public BooleanVariableExpression(String name) {
        this.name = name;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        return context.getVariable(name);
    }
    
    @Override
    public String toString() {
        return name;
    }
}

public class BooleanConstantExpression implements BooleanExpression {
    private boolean value;
    
    public BooleanConstantExpression(boolean value) {
        this.value = value;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        return value;
    }
    
    @Override
    public String toString() {
        return String.valueOf(value);
    }
}

// 非终结符表达式 - Non-terminal Expression
public class AndExpression implements BooleanExpression {
    private BooleanExpression leftExpression;
    private BooleanExpression rightExpression;
    
    public AndExpression(BooleanExpression leftExpression, BooleanExpression rightExpression) {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        return leftExpression.interpret(context) && rightExpression.interpret(context);
    }
    
    @Override
    public String toString() {
        return "(" + leftExpression + " AND " + rightExpression + ")";
    }
}

public class OrExpression implements BooleanExpression {
    private BooleanExpression leftExpression;
    private BooleanExpression rightExpression;
    
    public OrExpression(BooleanExpression leftExpression, BooleanExpression rightExpression) {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        return leftExpression.interpret(context) || rightExpression.interpret(context);
    }
    
    @Override
    public String toString() {
        return "(" + leftExpression + " OR " + rightExpression + ")";
    }
}

public class NotExpression implements BooleanExpression {
    private BooleanExpression expression;
    
    public NotExpression(BooleanExpression expression) {
        this.expression = expression;
    }
    
    @Override
    public boolean interpret(BooleanContext context) {
        return !expression.interpret(context);
    }
    
    @Override
    public String toString() {
        return "NOT(" + expression + ")";
    }
}

// 解析器 - Parser
public class BooleanExpressionParser {
    private String expression;
    private int index;
    
    public BooleanExpressionParser(String expression) {
        this.expression = expression.replaceAll("\\s+", "").toUpperCase();
        this.index = 0;
    }
    
    public BooleanExpression parse() {
        return parseExpression();
    }
    
    private BooleanExpression parseExpression() {
        BooleanExpression left = parseTerm();
        
        while (index < expression.length()) {
            String operator = parseOperator();
            if ("OR".equals(operator)) {
                BooleanExpression right = parseTerm();
                left = new OrExpression(left, right);
            } else {
                break;
            }
        }
        
        return left;
    }
    
    private BooleanExpression parseTerm() {
        BooleanExpression left = parseFactor();
        
        while (index < expression.length()) {
            String operator = parseOperator();
            if ("AND".equals(operator)) {
                BooleanExpression right = parseFactor();
                left = new AndExpression(left, right);
            } else {
                break;
            }
        }
        
        return left;
    }
    
    private BooleanExpression parseFactor() {
        if (index >= expression.length()) {
            throw new IllegalArgumentException("意外的表达式结束");
        }
        
        if (expression.startsWith("NOT", index)) {
            index += 3;
            BooleanExpression expr = parseFactor();
            return new NotExpression(expr);
        }
        
        if (expression.startsWith("TRUE", index)) {
            index += 4;
            return new BooleanConstantExpression(true);
        }
        
        if (expression.startsWith("FALSE", index)) {
            index += 5;
            return new BooleanConstantExpression(false);
        }
        
        if (expression.charAt(index) == '(') {
            index++;
            BooleanExpression expr = parseExpression();
            if (index >= expression.length() || expression.charAt(index) != ')') {
                throw new IllegalArgumentException("缺少右括号");
            }
            index++;
            return expr;
        }
        
        return parseVariable();
    }
    
    private BooleanExpression parseVariable() {
        StringBuilder variable = new StringBuilder();
        while (index < expression.length() && Character.isLetterOrDigit(expression.charAt(index))) {
            variable.append(expression.charAt(index));
            index++;
        }
        
        if (variable.length() == 0) {
            throw new IllegalArgumentException("期望变量名");
        }
        
        return new BooleanVariableExpression(variable.toString());
    }
    
    private String parseOperator() {
        if (index + 2 <= expression.length() && expression.substring(index, index + 2).equals("OR")) {
            index += 2;
            return "OR";
        }
        
        if (index + 3 <= expression.length() && expression.substring(index, index + 3).equals("AND")) {
            index += 3;
            return "AND";
        }
        
        return "";
    }
}

// 客户端使用 - Client Usage
public class BooleanExpressionDemo {
    public static void main(String[] args) {
        System.out.println("=== 布尔表达式解释器模式演示 ===");
        
        BooleanContext context = new BooleanContext();
        context.setVariable("A", true);
        context.setVariable("B", false);
        context.setVariable("C", true);
        
        // 测试不同的布尔表达式
        String[] expressions = {
            "TRUE",
            "FALSE",
            "A",
            "B",
            "NOT A",
            "A AND B",
            "A OR B",
            "A AND NOT B",
            "NOT (A AND B)",
            "(A OR B) AND C",
            "A AND B OR C",
            "NOT A AND NOT B",
            "NOT (A OR B)",
            "(A AND B) OR (NOT A AND C)"
        };
        
        for (String expr : expressions) {
            System.out.println("\n--- 表达式: " + expr + " ---");
            try {
                BooleanExpressionParser parser = new BooleanExpressionParser(expr);
                BooleanExpression expression = parser.parse();
                
                System.out.println("解析后的表达式: " + expression);
                boolean result = expression.interpret(context);
                System.out.println("计算结果: " + result);
                
            } catch (Exception e) {
                System.out.println("错误: " + e.getMessage());
            }
        }
        
        System.out.println("\n=== 演示完成 ===");
    }
}

3. 简单脚本语言解释器 (Simple Script Language Interpreter)

// 上下文类 - Context Class
public class ScriptContext {
    private Map<String, Integer> variables = new HashMap<>();
    private List<String> output = new ArrayList<>();
    
    public void setVariable(String name, int value) {
        variables.put(name, value);
    }
    
    public int getVariable(String name) {
        return variables.getOrDefault(name, 0);
    }
    
    public void print(String message) {
        output.add(message);
        System.out.println(message);
    }
    
    public List<String> getOutput() {
        return new ArrayList<>(output);
    }
}

// 抽象表达式 - Abstract Expression
public interface ScriptExpression {
    void interpret(ScriptContext context);
}

// 语句表达式 - Statement Expressions
public class AssignmentExpression implements ScriptExpression {
    private String variable;
    private Expression value;
    
    public AssignmentExpression(String variable, Expression value) {
        this.variable = variable;
        this.value = value;
    }
    
    @Override
    public void interpret(ScriptContext context) {
        int result = value.interpret(context);
        context.setVariable(variable, result);
        System.out.println(variable + " = " + result);
    }
    
    @Override
    public String toString() {
        return variable + " = " + value;
    }
}

public class PrintExpression implements ScriptExpression {
    private Expression expression;
    
    public PrintExpression(Expression expression) {
        this.expression = expression;
    }
    
    @Override
    public void interpret(ScriptContext context) {
        int result = expression.interpret(context);
        context.print(String.valueOf(result));
    }
    
    @Override
    public String toString() {
        return "PRINT " + expression;
    }
}

public class IfExpression implements ScriptExpression {
    private BooleanExpression condition;
    private List<ScriptExpression> thenStatements;
    private List<ScriptExpression> elseStatements;
    
    public IfExpression(BooleanExpression condition, List<ScriptExpression> thenStatements, List<ScriptExpression> elseStatements) {
        this.condition = condition;
        this.thenStatements = thenStatements;
        this.elseStatements = elseStatements;
    }
    
    @Override
    public void interpret(ScriptContext context) {
        boolean conditionResult = condition.interpret(context);
        System.out.println("IF " + condition + " = " + conditionResult);
        
        List<ScriptExpression> statements = conditionResult ? thenStatements : elseStatements;
        for (ScriptExpression statement : statements) {
            statement.interpret(context);
        }
    }
    
    @Override
    public String toString() {
        return "IF " + condition + " THEN {...} ELSE {...}";
    }
}

public class WhileExpression implements ScriptExpression {
    private BooleanExpression condition;
    private List<ScriptExpression> statements;
    
    public WhileExpression(BooleanExpression condition, List<ScriptExpression> statements) {
        this.condition = condition;
        this.statements = statements;
    }
    
    @Override
    public void interpret(ScriptContext context) {
        int iteration = 0;
        while (condition.interpret(context) && iteration < 1000) { // 防止无限循环
            System.out.println("WHILE " + condition + " = true (iteration " + iteration + ")");
            for (ScriptExpression statement : statements) {
                statement.interpret(context);
            }
            iteration++;
        }
        System.out.println("WHILE loop ended after " + iteration + " iterations");
    }
    
    @Override
    public String toString() {
        return "WHILE " + condition + " DO {...}";
    }
}

// 程序类 - Program Class
public class Program implements ScriptExpression {
    private List<ScriptExpression> statements;
    
    public Program(List<ScriptExpression> statements) {
        this.statements = statements;
    }
    
    @Override
    public void interpret(ScriptContext context) {
        System.out.println("=== 开始执行程序 ===");
        for (ScriptExpression statement : statements) {
            statement.interpret(context);
        }
        System.out.println("=== 程序执行完成 ===");
    }
    
    @Override
    public String toString() {
        return "Program with " + statements.size() + " statements";
    }
}

// 脚本解析器 - Script Parser
public class ScriptParser {
    private String script;
    private int index;
    
    public ScriptParser(String script) {
        this.script = script.replaceAll("\\s+", " ").trim();
        this.index = 0;
    }
    
    public Program parse() {
        List<ScriptExpression> statements = parseStatements();
        return new Program(statements);
    }
    
    private List<ScriptExpression> parseStatements() {
        List<ScriptExpression> statements = new ArrayList<>();
        while (index < script.length()) {
            skipWhitespace();
            if (index >= script.length()) break;
            
            ScriptExpression statement = parseStatement();
            if (statement != null) {
                statements.add(statement);
            }
        }
        return statements;
    }
    
    private ScriptExpression parseStatement() {
        if (match("LET")) {
            return parseAssignment();
        } else if (match("PRINT")) {
            return parsePrint();
        } else if (match("IF")) {
            return parseIf();
        } else if (match("WHILE")) {
            return parseWhile();
        }
        return null;
    }
    
    private AssignmentExpression parseAssignment() {
        skipWhitespace();
        String variable = parseIdentifier();
        skipWhitespace();
        if (!match("=")) {
            throw new IllegalArgumentException("期望 '='");
        }
        skipWhitespace();
        Expression value = parseExpression();
        return new AssignmentExpression(variable, value);
    }
    
    private PrintExpression parsePrint() {
        skipWhitespace();
        Expression expression = parseExpression();
        return new PrintExpression(expression);
    }
    
    private IfExpression parseIf() {
        skipWhitespace();
        BooleanExpression condition = parseBooleanExpression();
        skipWhitespace();
        if (!match("THEN")) {
            throw new IllegalArgumentException("期望 'THEN'");
        }
        
        List<ScriptExpression> thenStatements = new ArrayList<>();
        List<ScriptExpression> elseStatements = new ArrayList<>();
        
        // 简化的IF解析,假设THEN和ELSE块只有一个语句
        skipWhitespace();
        thenStatements.add(parseStatement());
        
        skipWhitespace();
        if (match("ELSE")) {
            skipWhitespace();
            elseStatements.add(parseStatement());
        }
        
        return new IfExpression(condition, thenStatements, elseStatements);
    }
    
    private WhileExpression parseWhile() {
        skipWhitespace();
        BooleanExpression condition = parseBooleanExpression();
        skipWhitespace();
        if (!match("DO")) {
            throw new IllegalArgumentException("期望 'DO'");
        }
        
        List<ScriptExpression> statements = new ArrayList<>();
        skipWhitespace();
        statements.add(parseStatement());
        
        return new WhileExpression(condition, statements);
    }
    
    private Expression parseExpression() {
        // 简化的表达式解析,只支持数字和变量
        if (Character.isDigit(currentChar())) {
            return parseNumber();
        } else {
            return new VariableExpression(parseIdentifier());
        }
    }
    
    private BooleanExpression parseBooleanExpression() {
        // 简化的布尔表达式解析
        if (match("TRUE")) {
            return new BooleanConstantExpression(true);
        } else if (match("FALSE")) {
            return new BooleanConstantExpression(false);
        } else {
            String variable = parseIdentifier();
            return new BooleanVariableExpression(variable);
        }
    }
    
    private NumberExpression parseNumber() {
        StringBuilder number = new StringBuilder();
        while (index < script.length() && Character.isDigit(currentChar())) {
            number.append(currentChar());
            index++;
        }
        return new NumberExpression(Integer.parseInt(number.toString()));
    }
    
    private String parseIdentifier() {
        StringBuilder identifier = new StringBuilder();
        while (index < script.length() && Character.isLetterOrDigit(currentChar())) {
            identifier.append(currentChar());
            index++;
        }
        return identifier.toString();
    }
    
    private void skipWhitespace() {
        while (index < script.length() && Character.isWhitespace(currentChar())) {
            index++;
        }
    }
    
    private boolean match(String token) {
        skipWhitespace();
        if (index + token.length() <= script.length() && 
            script.substring(index, index + token.length()).equalsIgnoreCase(token)) {
            index += token.length();
            return true;
        }
        return false;
    }
    
    private char currentChar() {
        return index < script.length() ? script.charAt(index) : '\0';
    }
}

// 客户端使用 - Client Usage
public class ScriptLanguageDemo {
    public static void main(String[] args) {
        System.out.println("=== 简单脚本语言解释器模式演示 ===");
        
        // 示例脚本
        String[] scripts = {
            "LET x = 10 PRINT x",
            "LET a = 5 LET b = 3 PRINT a + b",
            "LET n = 3 WHILE n DO PRINT n LET n = n - 1",
            "LET flag = TRUE IF flag THEN PRINT 1 ELSE PRINT 0"
        };
        
        for (String script : scripts) {
            System.out.println("\n--- 脚本: " + script + " ---");
            try {
                ScriptParser parser = new ScriptParser(script);
                Program program = parser.parse();
                
                System.out.println("解析后的程序: " + program);
                ScriptContext context = new ScriptContext();
                program.interpret(context);
                
                System.out.println("输出结果: " + context.getOutput());
                
            } catch (Exception e) {
                System.out.println("错误: " + e.getMessage());
                e.printStackTrace();
            }
        }
        
        System.out.println("\n=== 演示完成 ===");
    }
}

框架源码中的应用 (Framework Applications)

1. Java 正则表达式引擎

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class JavaRegexInterpreterDemo {
    public static void main(String[] args) {
        System.out.println("=== Java 正则表达式解释器模式 ===");
        
        System.out.println("Java 正则表达式引擎使用解释器模式:");
        System.out.println("1. Pattern.compile() - 编译正则表达式");
        System.out.println("2. Matcher.matches() - 匹配字符串");
        System.out.println("3. 正则表达式语法被解析为内部表示");
        System.out.println("4. 解释器遍历内部表示并执行匹配操作");
        
        // 示例
        String regex = "\\d{3}-\\d{3}-\\d{4}"; // 电话号码模式
        String text = "我的电话号码是 123-456-7890";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(text);
        
        if (matcher.find()) {
            System.out.println("找到匹配: " + matcher.group());
        }
    }
}

2. Spring Expression Language (SpEL)

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;

public class SpringExpressionInterpreterDemo {
    public static void main(String[] args) {
        System.out.println("=== Spring Expression Language 解释器模式 ===");
        
        System.out.println("SpEL 使用解释器模式解析和求值表达式:");
        System.out.println("1. ExpressionParser - 表达式解析器");
        System.out.println("2. EvaluationContext - 求值上下文");
        System.out.println("3. 表达式被解析为抽象语法树");
        System.out.println("4. 解释器遍历AST并计算结果");
        
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = new StandardEvaluationContext();
        
        // 简单表达式
        String expression = "2 + 3 * 4";
        int result = parser.parseExpression(expression).getValue(context, Integer.class);
        System.out.println("表达式: " + expression + " = " + result);
        
        // 带变量的表达式
        context.setVariable("x", 10);
        context.setVariable("y", 5);
        String varExpression = "#x + #y * 2";
        int varResult = parser.parseExpression(varExpression).getValue(context, Integer.class);
        System.out.println("变量表达式: " + varExpression + " = " + varResult);
    }
}

3. Java ScriptEngine (JavaScript 解释器)

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;

public class JavaScriptInterpreterDemo {
    public static void main(String[] args) {
        System.out.println("=== Java ScriptEngine 解释器模式 ===");
        
        System.out.println("Java ScriptEngine 使用解释器模式执行脚本:");
        System.out.println("1. ScriptEngineManager - 脚本引擎管理器");
        System.out.println("2. ScriptEngine - 脚本引擎");
        System.out.println("3. 脚本代码被解释执行");
        
        try {
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName("JavaScript");
            
            // 简单表达式
            String script = "var x = 10; var y = 20; x + y;";
            Object result = engine.eval(script);
            System.out.println("JavaScript 结果: " + result);
            
            // 函数定义
            String functionScript = 
                "function add(a, b) { return a + b; } add(5, 3);";
            Object functionResult = engine.eval(functionScript);
            System.out.println("函数调用结果: " + functionResult);
            
        } catch (ScriptException e) {
            System.out.println("脚本错误: " + e.getMessage());
        }
    }
}

优缺点 (Pros and Cons)

优点 (Advantages)

  • 灵活性: 可以动态地解释和执行代码
  • 可扩展性: 易于添加新的表达式类型
  • 简单性: 对于简单的语言,实现相对简单
  • 可读性: 文法表示清晰,易于理解
  • 动态性: 可以在运行时改变和扩展行为

缺点 (Disadvantages)

  • 性能问题: 解释执行通常比编译执行慢
  • 复杂性: 对于复杂的语言,实现变得复杂
  • 调试困难: 解释器代码难以调试和维护
  • 错误处理: 错误处理和报告可能不够完善
  • 内存消耗: 可能需要维护复杂的内部状态

最佳实践 (Best Practices)

1. 文法设计的原则

// 保持文法简单
public interface SimpleExpression {
    int interpret(Context context);
}

// 避免过于复杂的递归结构
public class SimpleParser {
    public Expression parse(String input) {
        // 使用简单的递归下降解析
        return parseSimpleExpression(input);
    }
}

2. 性能优化策略

// 缓存编译结果
public class ExpressionCache {
    private Map<String, Expression> cache = new HashMap<>();
    
    public Expression getOrCompile(String expression) {
        return cache.computeIfAbsent(expression, this::compile);
    }
    
    private Expression compile(String expression) {
        // 编译表达式并缓存
        return new CompiledExpression(expression);
    }
}

// 使用编译器而非解释器
public class ExpressionCompiler {
    public CompiledExpression compile(Expression expr) {
        // 将表达式编译为字节码
        return new CompiledExpression(expr);
    }
}

3. 错误处理和调试

public class RobustInterpreter {
    public Result interpret(String input) {
        try {
            Expression expr = parse(input);
            validate(expr);
            return Result.success(expr.interpret(context));
        } catch (ParseException e) {
            return Result.failure("解析错误: " + e.getMessage(), e.getPosition());
        } catch (ValidationException e) {
            return Result.failure("验证错误: " + e.getMessage());
        } catch (RuntimeException e) {
            return Result.failure("运行时错误: " + e.getMessage());
        }
    }
    
    private void validate(Expression expr) {
        // 语义验证
        if (hasCircularReference(expr)) {
            throw new ValidationException("循环引用检测");
        }
    }
}

相关模式 (Related Patterns)

  • 组合模式 (Composite): 解释器模式通常使用组合模式来表示文法结构
  • 访问者模式 (Visitor): 可以用于遍历解释器中的抽象语法树
  • 策略模式 (Strategy): 可以用于选择不同的解释策略
  • 状态模式 (State): 可以用于管理解释器的状态

总结 (Summary)

解释器模式是一种专门用于处理语言解释的行为型设计模式。它通过定义语言的文法表示和相应的解释器,使得程序能够动态地解释和执行代码。虽然这种模式在性能上可能不如编译器,但它提供了极大的灵活性和动态性。

解释器模式的核心价值在于:

  1. 动态性: 可以在运行时解释和执行代码
  2. 灵活性: 易于扩展和修改语言特性
  3. 可维护性: 文法表示清晰,易于理解和维护
  4. 适用性: 特别适合处理简单的领域特定语言

通过合理使用解释器模式,可以为应用程序添加强大的脚本能力和动态行为,特别适用于需要处理简单表达式、规则引擎或配置语言的场景。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐