想象一下,你要开发一个智能计算器,用户输入"(3+5)*2-1",程序就能自动计算出结果15。或者你要设计一个配置系统,支持类似"if user.age > 18 then allow"这样的规则语法。解释器模式就像是给你的程序装了一个"翻译官",能够理解和执行各种自定义的表达式和语言!
🤔 什么是解释器模式?
解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言的文法表示,并提供一个解释器来处理这种语言中的句子。
说人话就是:给你的程序装一个"语言大脑",让它能理解和执行自定义的表达式!
生活中的解释器模式
计算器就是最好的例子:
- 你输入:“2 + 3 * 4”
- 计算器理解:先算乘法(3*4=12),再算加法(2+12=14)
- 最终输出:14
音乐播放器读乐谱:
- 乐谱上写着:♪ ♫ ♪ ♩
- 播放器解释:四分音符 八分音符 四分音符 二分音符
- 最终输出:对应的音乐
Google翻译:
- 输入:“Hello World”
- 翻译器解释:英语句子,主语+宾语结构
- 输出:“你好世界”
编程语言解释器:
// Java代码
if (age > 18) {
System.out.println("成年人");
}
// JVM解释器理解:
// 1. 条件判断语句
// 2. 比较age变量与常量18
// 3. 如果为真,执行打印语句
💼 解释器模式的应用场景
1. 数学表达式计算器
// 用户输入复杂的数学表达式
String expression = "(3 + 5) * 2 - 4 / 2";
Calculator calculator = new Calculator();
double result = calculator.evaluate(expression); // 结果:14.0
2. 业务规则引擎
// 电商系统的促销规则
String rule = "if (user.level == 'VIP' AND order.amount > 1000) then discount = 0.8";
RuleEngine engine = new RuleEngine();
boolean result = engine.evaluate(rule, context);
3. SQL查询解析
// 简化版SQL解析
String sql = "SELECT name, age FROM users WHERE age > 18";
SQLParser parser = new SQLParser();
QueryResult result = parser.execute(sql);
4. 配置文件解析
// 自定义配置语言
String config = """
server {
port = 8080
host = "localhost"
if env == "prod" then ssl = true
}
""";
ConfigParser parser = new ConfigParser();
Configuration conf = parser.parse(config);

⚙️ 解释器模式的核心原理
核心组件
- 抽象表达式(Abstract Expression):定义解释操作的接口
- 终结符表达式(Terminal Expression):实现语法中终结符相关的解释操作
- 非终结符表达式(Non-terminal Expression):实现语法中非终结符相关的解释操作
- 环境(Context):包含解释器之外的一些全局信息
- 客户端(Client):构建抽象语法树,调用解释操作
代码实现:数学表达式计算器
1. 抽象表达式接口
/**
* 抽象表达式接口 - 解释器模式的核心
*/
public interface Expression {
/**
* 解释表达式,返回计算结果
* @param context 上下文环境(可存储变量值等)
* @return 表达式的计算结果
*/
double interpret(Context context);
}
2. 上下文环境
/**
* 上下文类 - 存储变量和全局信息
*/
public class Context {
// 存储变量值,例如 x=10, y=20
private Map<String, Double> variables = new HashMap<>();
public void setVariable(String name, double value) {
variables.put(name, value);
System.out.println("📝 设置变量:" + name + " = " + value);
}
public double getVariable(String name) {
Double value = variables.get(name);
if (value == null) {
throw new RuntimeException("未定义的变量: " + name);
}
System.out.println("🔍 获取变量:" + name + " = " + value);
return value;
}
public boolean hasVariable(String name) {
return variables.containsKey(name);
}
// 打印所有变量
public void printVariables() {
System.out.println("📋 当前变量:" + variables);
}
}
3. 终结符表达式(数字和变量)
/**
* 数字表达式 - 终结符表达式
*/
public class NumberExpression implements Expression {
private double number;
public NumberExpression(double number) {
this.number = number;
System.out.println("🔢 创建数字表达式:" + number);
}
@Override
public double interpret(Context context) {
System.out.println("📊 解释数字:" + number);
return number;
}
@Override
public String toString() {
return String.valueOf(number);
}
}
/**
* 变量表达式 - 终结符表达式
*/
public class VariableExpression implements Expression {
private String variableName;
public VariableExpression(String variableName) {
this.variableName = variableName;
System.out.println("🏷️ 创建变量表达式:" + variableName);
}
@Override
public double interpret(Context context) {
double value = context.getVariable(variableName);
System.out.println("📊 解释变量:" + variableName + " = " + value);
return value;
}
@Override
public String toString() {
return variableName;
}
}
4. 非终结符表达式(运算符)
/**
* 加法表达式 - 非终结符表达式
*/
public class AddExpression implements Expression {
private Expression left;
private Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
System.out.println("➕ 创建加法表达式:(" + left + " + " + right + ")");
}
@Override
public double interpret(Context context) {
double leftValue = left.interpret(context);
double rightValue = right.interpret(context);
double result = leftValue + rightValue;
System.out.println("🧮 计算加法:" + leftValue + " + " + rightValue + " = " + result);
return result;
}
@Override
public String toString() {
return "(" + left + " + " + right + ")";
}
}
/**
* 减法表达式 - 非终结符表达式
*/
public class SubtractExpression implements Expression {
private Expression left;
private Expression right;
public SubtractExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
System.out.println("➖ 创建减法表达式:(" + left + " - " + right + ")");
}
@Override
public double interpret(Context context) {
double leftValue = left.interpret(context);
double rightValue = right.interpret(context);
double result = leftValue - rightValue;
System.out.println("🧮 计算减法:" + leftValue + " - " + rightValue + " = " + result);
return result;
}
@Override
public String toString() {
return "(" + left + " - " + right + ")";
}
}
/**
* 乘法表达式 - 非终结符表达式
*/
public class MultiplyExpression implements Expression {
private Expression left;
private Expression right;
public MultiplyExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
System.out.println("✖️ 创建乘法表达式:(" + left + " * " + right + ")");
}
@Override
public double interpret(Context context) {
double leftValue = left.interpret(context);
double rightValue = right.interpret(context);
double result = leftValue * rightValue;
System.out.println("🧮 计算乘法:" + leftValue + " * " + rightValue + " = " + result);
return result;
}
@Override
public String toString() {
return "(" + left + " * " + right + ")";
}
}
/**
* 除法表达式 - 非终结符表达式
*/
public class DivideExpression implements Expression {
private Expression left;
private Expression right;
public DivideExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
System.out.println("➗ 创建除法表达式:(" + left + " / " + right + ")");
}
@Override
public double interpret(Context context) {
double leftValue = left.interpret(context);
double rightValue = right.interpret(context);
if (rightValue == 0) {
throw new ArithmeticException("除数不能为零");
}
double result = leftValue / rightValue;
System.out.println("🧮 计算除法:" + leftValue + " / " + rightValue + " = " + result);
return result;
}
@Override
public String toString() {
return "(" + left + " / " + right + ")";
}
}
5. 表达式解析器(语法分析器)
/**
* 表达式解析器 - 将字符串转换为表达式树
*/
public class ExpressionParser {
/**
* 解析表达式字符串,构建表达式树
* 支持的语法:数字、变量、+、-、*、/、括号
* 运算符优先级:() > */ > +-
*/
public Expression parse(String expression) {
System.out.println("🔍 开始解析表达式:" + expression);
// 去除空格
expression = expression.replaceAll("\\s+", "");
// 词法分析:将字符串分解为token
List<String> tokens = tokenize(expression);
System.out.println("📝 词法分析结果:" + tokens);
// 语法分析:构建表达式树
Expression result = parseExpression(tokens, 0).expression;
System.out.println("🌲 表达式树构建完成:" + result);
return result;
}
/**
* 词法分析:将表达式分解为token
*/
private List<String> tokenize(String expression) {
List<String> tokens = new ArrayList<>();
StringBuilder current = new StringBuilder();
for (char c : expression.toCharArray()) {
if (Character.isDigit(c) || c == '.') {
current.append(c);
} else if (Character.isLetter(c)) {
current.append(c);
} else {
if (current.length() > 0) {
tokens.add(current.toString());
current.setLength(0);
}
tokens.add(String.valueOf(c));
}
}
if (current.length() > 0) {
tokens.add(current.toString());
}
return tokens;
}
/**
* 语法分析结果包装类
*/
private static class ParseResult {
Expression expression;
int nextIndex;
ParseResult(Expression expression, int nextIndex) {
this.expression = expression;
this.nextIndex = nextIndex;
}
}
/**
* 解析表达式(处理 + 和 - 运算符)
*/
private ParseResult parseExpression(List<String> tokens, int index) {
ParseResult left = parseTerm(tokens, index);
while (left.nextIndex < tokens.size()) {
String operator = tokens.get(left.nextIndex);
if (!operator.equals("+") && !operator.equals("-")) {
break;
}
ParseResult right = parseTerm(tokens, left.nextIndex + 1);
if (operator.equals("+")) {
left.expression = new AddExpression(left.expression, right.expression);
} else {
left.expression = new SubtractExpression(left.expression, right.expression);
}
left.nextIndex = right.nextIndex;
}
return left;
}
/**
* 解析项(处理 * 和 / 运算符)
*/
private ParseResult parseTerm(List<String> tokens, int index) {
ParseResult left = parseFactor(tokens, index);
while (left.nextIndex < tokens.size()) {
String operator = tokens.get(left.nextIndex);
if (!operator.equals("*") && !operator.equals("/")) {
break;
}
ParseResult right = parseFactor(tokens, left.nextIndex + 1);
if (operator.equals("*")) {
left.expression = new MultiplyExpression(left.expression, right.expression);
} else {
left.expression = new DivideExpression(left.expression, right.expression);
}
left.nextIndex = right.nextIndex;
}
return left;
}
/**
* 解析因子(处理数字、变量和括号)
*/
private ParseResult parseFactor(List<String> tokens, int index) {
if (index >= tokens.size()) {
throw new RuntimeException("表达式不完整");
}
String token = tokens.get(index);
// 处理括号
if (token.equals("(")) {
ParseResult result = parseExpression(tokens, index + 1);
if (result.nextIndex >= tokens.size() || !tokens.get(result.nextIndex).equals(")")) {
throw new RuntimeException("缺少右括号");
}
return new ParseResult(result.expression, result.nextIndex + 1);
}
// 处理数字
if (isNumber(token)) {
return new ParseResult(new NumberExpression(Double.parseDouble(token)), index + 1);
}
// 处理变量
if (isVariable(token)) {
return new ParseResult(new VariableExpression(token), index + 1);
}
throw new RuntimeException("无法识别的token: " + token);
}
private boolean isNumber(String token) {
try {
Double.parseDouble(token);
return true;
} catch (NumberFormatException e) {
return false;
}
}
private boolean isVariable(String token) {
return token.matches("[a-zA-Z][a-zA-Z0-9]*");
}
}
6. 计算器客户端
/**
* 智能计算器 - 客户端类
*/
public class SmartCalculator {
private ExpressionParser parser;
private Context context;
public SmartCalculator() {
this.parser = new ExpressionParser();
this.context = new Context();
System.out.println("🧮 智能计算器启动成功!");
}
/**
* 设置变量值
*/
public void setVariable(String name, double value) {
context.setVariable(name, value);
}
/**
* 计算表达式
*/
public double calculate(String expression) {
System.out.println("\n" + "=".repeat(50));
System.out.println("🎯 计算表达式:" + expression);
System.out.println("=".repeat(50));
try {
// 解析表达式
Expression expr = parser.parse(expression);
// 解释执行
System.out.println("\n🚀 开始执行计算...");
double result = expr.interpret(context);
System.out.println("\n✅ 计算完成!");
System.out.println("📊 最终结果:" + expression + " = " + result);
return result;
} catch (Exception e) {
System.err.println("❌ 计算出错:" + e.getMessage());
throw e;
}
}
/**
* 打印变量列表
*/
public void printVariables() {
context.printVariables();
}
public static void main(String[] args) {
SmartCalculator calculator = new SmartCalculator();
System.out.println("🧪 === 智能计算器测试 === 🧪\n");
// 测试1:简单四则运算
System.out.println("📋 测试1:基础四则运算");
calculator.calculate("3 + 5");
calculator.calculate("10 - 4");
calculator.calculate("6 * 7");
calculator.calculate("15 / 3");
// 测试2:复合运算(运算符优先级)
System.out.println("\n📋 测试2:运算符优先级");
calculator.calculate("3 + 5 * 2"); // 应该是 3 + (5 * 2) = 13
calculator.calculate("10 - 4 / 2"); // 应该是 10 - (4 / 2) = 8
calculator.calculate("2 * 3 + 4 * 5"); // 应该是 (2 * 3) + (4 * 5) = 26
// 测试3:括号运算
System.out.println("\n📋 测试3:括号改变运算顺序");
calculator.calculate("(3 + 5) * 2"); // 应该是 8 * 2 = 16
calculator.calculate("10 / (4 - 2)"); // 应该是 10 / 2 = 5
calculator.calculate("((2 + 3) * 4) - (6 / 2)"); // ((5) * 4) - (3) = 17
// 测试4:变量运算
System.out.println("\n📋 测试4:变量支持");
calculator.setVariable("x", 10);
calculator.setVariable("y", 5);
calculator.printVariables();
calculator.calculate("x + y"); // 10 + 5 = 15
calculator.calculate("x * y - 10"); // 10 * 5 - 10 = 40
calculator.calculate("(x + y) * 2"); // (10 + 5) * 2 = 30
// 测试5:复杂表达式
System.out.println("\n📋 测试5:复杂表达式");
calculator.setVariable("a", 2);
calculator.setVariable("b", 3);
calculator.setVariable("c", 4);
calculator.calculate("a * b + c"); // 2 * 3 + 4 = 10
calculator.calculate("(a + b) * c - a"); // (2 + 3) * 4 - 2 = 18
calculator.calculate("a * (b + c) / (a + 1)"); // 2 * (3 + 4) / (2 + 1) = 14/3 ≈ 4.67
System.out.println("\n🎉 所有测试完成!");
// 性能测试
System.out.println("\n⚡ 性能测试:");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
calculator.calculate("(10 + 5) * 2 - 3");
}
long endTime = System.currentTimeMillis();
System.out.println("执行1000次复杂表达式耗时:" + (endTime - startTime) + "毫秒");
}
}

🚀 解释器模式的扩展应用
1. Spring表达式语言(SpEL)
Spring中的SpEL就是解释器模式的经典应用:
@Component
public class SpELDemo {
@Value("#{systemProperties['java.version']}")
private String javaVersion;
@Value("#{T(java.lang.Math).random() * 100}")
private double randomNumber;
// 在代码中使用SpEL
public void demonstrateSpEL() {
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
// 设置变量
context.setVariable("user", new User("张三", 25));
// 解析并执行表达式
Expression exp = parser.parseExpression("#user.name + ' 今年 ' + #user.age + ' 岁'");
String result = exp.getValue(context, String.class);
System.out.println(result); // 输出:张三 今年 25 岁
// 条件表达式
Expression condExp = parser.parseExpression("#user.age >= 18 ? '成年人' : '未成年'");
String ageCategory = condExp.getValue(context, String.class);
System.out.println(ageCategory); // 输出:成年人
}
}
2. 正则表达式引擎
正则表达式本质上也是解释器模式:
/**
* 简化版正则表达式解释器
*/
public class SimpleRegexInterpreter {
public static void main(String[] args) {
// Java内置的正则表达式引擎
Pattern pattern = Pattern.compile("\\d{3}-\\d{4}-\\d{4}");
Matcher matcher = pattern.matcher("136-1234-5678");
System.out.println("匹配结果:" + matcher.matches());
// 自定义简单的模式匹配
SimplePattern simplePattern = new SimplePattern("a*b");
System.out.println("匹配 'aaab':" + simplePattern.matches("aaab"));
System.out.println("匹配 'ab':" + simplePattern.matches("ab"));
System.out.println("匹配 'b':" + simplePattern.matches("b"));
}
}
class SimplePattern {
private String pattern;
public SimplePattern(String pattern) {
this.pattern = pattern;
}
public boolean matches(String input) {
// 简化的模式匹配逻辑(这里只是示例)
if (pattern.equals("a*b")) {
return input.matches("a*b");
}
return false;
}
}
3. SQL解析器
SQL解析也是解释器模式的典型应用:
/**
* 简化版SQL解释器
*/
public class SimpleSQLInterpreter {
// SQL表达式接口
interface SQLExpression {
void execute(DatabaseContext context);
}
// SELECT语句
static class SelectStatement implements SQLExpression {
private List<String> columns;
private String tableName;
private WhereClause whereClause;
public SelectStatement(List<String> columns, String tableName, WhereClause whereClause) {
this.columns = columns;
this.tableName = tableName;
this.whereClause = whereClause;
}
@Override
public void execute(DatabaseContext context) {
System.out.println("🔍 执行查询:");
System.out.println(" 表名:" + tableName);
System.out.println(" 字段:" + columns);
if (whereClause != null) {
System.out.println(" 条件:" + whereClause);
}
// 模拟查询执行
List<Map<String, Object>> results = context.query(tableName, columns, whereClause);
System.out.println(" 结果:" + results.size() + " 条记录");
}
}
// WHERE子句
static class WhereClause {
private String condition;
public WhereClause(String condition) {
this.condition = condition;
}
@Override
public String toString() {
return condition;
}
}
// 数据库上下文
static class DatabaseContext {
public List<Map<String, Object>> query(String table, List<String> columns, WhereClause where) {
// 模拟数据库查询
return Arrays.asList(
Map.of("id", 1, "name", "张三", "age", 25),
Map.of("id", 2, "name", "李四", "age", 30)
);
}
}
public static void main(String[] args) {
// 构建SQL表达式
List<String> columns = Arrays.asList("name", "age");
WhereClause where = new WhereClause("age > 18");
SelectStatement select = new SelectStatement(columns, "users", where);
// 执行SQL
DatabaseContext context = new DatabaseContext();
select.execute(context);
}
}
4. 配置文件解析器
/**
* 配置文件解释器
*/
public class ConfigInterpreter {
// 配置表达式接口
interface ConfigExpression {
void apply(ApplicationContext context);
}
// 服务器配置
static class ServerConfig implements ConfigExpression {
private int port;
private String host;
public ServerConfig(int port, String host) {
this.port = port;
this.host = host;
}
@Override
public void apply(ApplicationContext context) {
context.setServerPort(port);
context.setServerHost(host);
System.out.println("🌐 配置服务器:" + host + ":" + port);
}
}
// 数据库配置
static class DatabaseConfig implements ConfigExpression {
private String url;
private String username;
public DatabaseConfig(String url, String username) {
this.url = url;
this.username = username;
}
@Override
public void apply(ApplicationContext context) {
context.setDatabaseUrl(url);
context.setDatabaseUsername(username);
System.out.println("🗄️ 配置数据库:" + url + " (" + username + ")");
}
}
// 应用上下文
static class ApplicationContext {
private int serverPort;
private String serverHost;
private String databaseUrl;
private String databaseUsername;
// Setters
public void setServerPort(int port) { this.serverPort = port; }
public void setServerHost(String host) { this.serverHost = host; }
public void setDatabaseUrl(String url) { this.databaseUrl = url; }
public void setDatabaseUsername(String username) { this.databaseUsername = username; }
public void printConfig() {
System.out.println("\n📋 应用配置总览:");
System.out.println(" 服务器:" + serverHost + ":" + serverPort);
System.out.println(" 数据库:" + databaseUrl + " (" + databaseUsername + ")");
}
}
public static void main(String[] args) {
// 解析配置文件
List<ConfigExpression> configs = Arrays.asList(
new ServerConfig(8080, "localhost"),
new DatabaseConfig("jdbc:mysql://localhost:3306/mydb", "admin")
);
// 应用配置
ApplicationContext context = new ApplicationContext();
configs.forEach(config -> config.apply(context));
context.printConfig();
}
}
🎯 面试热点问题
Q1: 解释器模式和策略模式有什么区别?
面试官经常问的问题!
| 对比维度 | 解释器模式 | 策略模式 |
|---|---|---|
| 设计目的 | 定义语言文法,解释语句 | 定义算法族,相互替换 |
| 结构复杂度 | 复杂,需要语法树 | 简单,一个接口多个实现 |
| 使用场景 | 需要解释执行表达式/语言 | 需要动态选择算法 |
| 扩展性 | 难扩展,修改文法影响大 | 易扩展,添加新策略简单 |
记忆技巧:
- 解释器模式:翻译官,把一种语言翻译成另一种
- 策略模式:工具箱,根据需要选择不同的工具
Q2: 解释器模式的优缺点?
优点:
- ✅ 易于实现语法:每个语法规则对应一个类,结构清晰
- ✅ 易于扩展语法:增加新的语法规则只需要添加新类
- ✅ 易于修改和扩展:每个表达式类独立,互不影响
缺点:
- ❌ 类的数量增加:每个语法规则都需要一个类
- ❌ 执行效率较低:递归调用,性能不如直接编译
- ❌ 适用范围有限:只适合简单的语法,复杂语法会导致类爆炸
Q3: 何时使用解释器模式?
适用场景:
- 简单语法:语言的语法相对简单
- 执行效率不是关键:不需要高性能的执行速度
- 频繁变化的语法:语法规则经常需要修改和扩展
- 自定义DSL:需要实现特定领域的小语言
经典应用:
- 数学表达式计算器
- 简单的脚本语言解释器
- 配置文件解析器
- 正则表达式引擎
- SQL解析器
不适用场景:
- 复杂的编程语言(如Java、C++)
- 对性能要求极高的场景
- 语法规则过于复杂的情况
Q4: 解释器模式在开源框架中的应用?
1. Spring表达式语言(SpEL)
// Spring中大量使用SpEL解释器
@Value("#{configProperties.timeout ?: 5000}")
private int timeout;
@PreAuthorize("hasRole('ADMIN') and #user.department == 'IT'")
public void adminOperation(User user) { ... }
2. Apache Commons JEXL
// 数学表达式解释器
JexlEngine jexl = new JexlBuilder().create();
JexlExpression e = jexl.createExpression("foo.innerFoo.bar()");
JexlContext jc = new MapContext();
jc.set("foo", new Foo());
Object o = e.evaluate(jc);
3. Drools规则引擎
// 业务规则表达式
rule "Discount"
when
$order : Order(amount > 1000)
$customer : Customer(level == "VIP")
then
$order.setDiscount(0.1);
end
Q5: 如何优化解释器模式的性能?
优化策略:
1. 缓存表达式树
public class CachedExpressionParser {
private Map<String, Expression> cache = new ConcurrentHashMap<>();
public Expression parse(String expression) {
return cache.computeIfAbsent(expression, this::doParse);
}
private Expression doParse(String expression) {
// 实际的解析逻辑
return new ExpressionParser().parse(expression);
}
}
2. 预编译表达式
public class CompiledExpression {
private final Expression expression;
private final Set<String> variables;
public CompiledExpression(String expr) {
this.expression = parser.parse(expr);
this.variables = extractVariables(expr);
}
public double evaluate(Map<String, Double> values) {
Context context = new Context();
variables.forEach(var -> context.setVariable(var, values.get(var)));
return expression.interpret(context);
}
}
3. 使用访问者模式优化
// 将解释逻辑从表达式类中分离出来
public interface ExpressionVisitor {
double visitNumber(NumberExpression expr);
double visitAdd(AddExpression expr);
double visitMultiply(MultiplyExpression expr);
}
public class OptimizedInterpreter implements ExpressionVisitor {
// 优化的解释逻辑
@Override
public double visitAdd(AddExpression expr) {
return expr.getLeft().accept(this) + expr.getRight().accept(this);
}
}
💡 总结
解释器模式就像是给你的程序装了一个"语言大脑",让它能理解和执行各种自定义的表达式和语言!
记住这个口诀:
语法规则对应类,表达式树递归推
简单语言解释器,DSL实现靠它追!
实战建议:
- 识别适用场景:简单语法 + 性能要求不高 + 需要灵活扩展
- 合理设计文法:保持语法简单,避免过度复杂
- 考虑性能优化:使用缓存、预编译等技术
- 结合其他模式:可以与访问者模式、工厂模式结合使用
解释器模式不仅仅是一种设计模式,更是一种语言处理的编程思想。当你需要创建自己的小语言或表达式系统时,解释器模式就是你的最佳选择!
看完这篇文章,下次遇到需要解析表达式的需求时,记得想想解释器模式!让你的程序从"哑巴"变成"语言大师"~ 记得点赞👍收藏⭐分享🔄!
210

被折叠的 条评论
为什么被折叠?



