在日常开发中,我们经常会写类似这样的代码
int result = 10 + 20;
这样的代码当然没有任何问题,但如果我们希望把"计算规则"本身抽象出来,让它可以被自由组合、扩展,甚至在运行时动态决定执行逻辑时,单纯的表达式就显得不够灵活了。
解释器模式(Interpreter Pattern)正是为了解决这一类问题而存在的。
它的核心思想是:把规则本身抽象成对象,通过对象组合来完成逻辑解释和执行。
下面我将通过一个最简单、最直观的例子,一步步展示解释器模式的基本结构。
1.定义解释器接口
cs
public interface IExpression
{
int Interpret();
}
2.定义终结符
终结符是解释器中最小的单位,表示不可再拆分的具体值,例如数字、常量等。
cs
// 2. 终结符:代表具体的数字
public class NumberExpression : IExpression
{
private int _number;
public NumberExpression(int number) => _number = number;
public int Interpret() => _number;
}
3.定义具体逻辑解释器
非终结符用于表示语法规则,它通常由多个表达式组合而成,并在 Interpret() 中定义具体的运算或逻辑。
cs
// 3. 非终结符:代表"加法"逻辑
public class AddExpression : IExpression
{
private IExpression _left;
private IExpression _right;
public AddExpression(IExpression left, IExpression right)
{
_left = left;
_right = right;
}
// 真正的"解释"逻辑:把左右两边相加
public int Interpret() => _left.Interpret() + _right.Interpret();
}
4.使用
cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
void Start()
{
IExpression one = new NumberExpression(10);
IExpression two = new NumberExpression(20);
IExpression sum = new AddExpression(one, two);
// 执行解释
Debug.Log("结果是: " + sum.Interpret());
}
}
5.运行结果
将Player加到场景中的空对象上然后运行游戏,可以看到计算结果已经被正确的打印了出来。

总结
通过这个例子可以看到,解释器模式的本质并不复杂:
-
终结符表示最基本、不可再拆分的元素
-
非终结符负责组合这些元素,并定义解释规则
-
客户端通过组合表达式对象,构建出一棵表达式树
-
最终只需要调用一次
Interpret(),即可完成整个规则的执行
需要注意的是,解释器模式并不适合所有场景。
如果逻辑非常简单、规则固定不变,直接使用普通代码往往更加直观。
但当规则本身需要被抽象、组合,或者未来存在扩展需求时,解释器模式就能很好地体现它的价值。