27. 解释器模式
约 1284 字大约 4 分钟
2026-03-29
定义
解释器模式(interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
人话:解释器模式就像正则表达式匹配字符串的过程。比如你要校验一个字符串是不是合法的邮箱、手机号,或者从一段文本中提取特定格式的数据,这时候就会用到正则表达式。
如果不用解释器模式来设计,就相当于你每次都手写一堆判断逻辑,比如:
- 先判断有没有 @
- 再判断前面是不是字母或数字
- 再判断后面是不是域名格式
- 还要考虑各种边界情况
这些判断通常会写成一大堆 if-else,不仅复杂,而且一旦规则变化(比如邮箱规则调整),就需要到处修改代码。这在软件中就属于规则分散、逻辑混乱、难以维护。
而使用解释器模式之后,就相当于把这些规则抽象成一套“语法”,也就是正则表达式,比如:
- \d+ → 表示一个或多个数字
- [a-zA-Z]+ → 表示字母
- \w+@\w+.\w+ → 表示一个简单的邮箱规则
然后解释器会把这个表达式解析成一棵“语法树”,再按照规则一步步去匹配输入的字符串。
这样一来:
- 每一段规则(数字、字母、符号)就是一个“表达式”(Expression)
- 多个规则组合起来形成完整的匹配逻辑(语法结构)
- 解释器负责按照规则去解析和执行
比如:
正则 \d{3}-\d
- → 表示“3位数字-4位数字”
- → 输入 123-4567 → 匹配成功
- → 输入 12-4567 → 匹配失败
在软件中也是一样:解释器模式就是把复杂的规则表达成一种“语言”,再用程序去解释执行这门语言。这样当规则变化时,只需要修改“表达式”(比如正则),而不需要改底层代码,从而让系统更加灵活、清晰、易扩展。
解释器模式(interpreter)结构图
AbstractExpression类——抽象表达式:
// AbstractExpression(抽象表达式)
abstract class AbstractExpression
{
// 解释操作
public abstract void Interpret(Context context);
}TerminalExpression类——终结符表达式:
// TerminalExpression(终结符表达式)
class TerminalExpression : AbstractExpression
{
public override void Interpret(Context context)
{
Console.WriteLine("终端解释器");
}
}NonterminalExpression类——非终结符表达式:
// NonterminalExpression(非终结符表达式)
class NonterminalExpression : AbstractExpression
{
public override void Interpret(Context context)
{
Console.WriteLine("非终端解释器");
}
}Context类——上下文环境:
// Context(上下文)
class Context
{
private string input;
public string Input
{
get { return input; }
set { input = value; }
}
private string output;
public string Output
{
get { return output; }
set { output = value; }
}
}客户端代码:
static void Main(string[] args)
{
Context context = new Context();
IList<AbstractExpression> list = new List<AbstractExpression>();
// 构建语法树
list.Add(new TerminalExpression());
list.Add(new NonterminalExpression());
list.Add(new TerminalExpression());
list.Add(new TerminalExpression());
// 解释执行
foreach (AbstractExpression exp in list)
{
exp.Interpret(context);
}
Console.Read();
}运行结果:
终端解释器
非终端解释器
终端解释器
终端解释器解释器模式需要解决的是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
通常当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
用了解释器模式,就意味着可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。
解释器模式也有不足的,解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。
