解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
意图:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
主要解决:对于一些固定文法构建一个解释句子的解释器。
何时使用:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
如何解决:构建语法树,定义终结符与非终结符。
关键代码:构建环境类,包含解释器之外的一些全局信息,一般是 HashMap。
应用实例:编译器、运算表达式计算。
优点: 1、可扩展性比较好,灵活。 2、增加了新的解释表达式的方式。 3、易于实现简单文法。
缺点: 1、可利用场景比较少。 2、对于复杂的文法比较难维护。 3、解释器模式会引起类膨胀。 4、解释器模式采用递归调用方法。
使用场景: 1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。 2、一些重复出现的问题可以用一种简单的语言来进行表达。 3、一个简单语法需要解释的场景。

在很多场合都需要把数字转换成中文,我们就可以使用解释器来实现该功能,把给定的数字解释成符合语法规范的汉字表示法。实现代码如下:
static void Main(string[] args)
{
string roman = "五亿七千三百零二万六千四百五十二";
//分解:((五)亿)((七千)(三百)(零)(二)万)
//((六千)(四百)(五十)(二))
Context context = new Context(roman);
ArrayList tree = new ArrayList();
tree.Add(new GeExpression());
tree.Add(new ShiExpression());
tree.Add(new BaiExpression());
tree.Add(new QianExpression());
tree.Add(new WanExpression());
tree.Add(new YiExpression());
foreach (Expression exp in tree)
{
exp.Interpreter(context);
}
Console.Write(context.Data);
}
// 抽象表达式
public abstract class Expression
{
protected Dictionary<string, int> table = new Dictionary<string, int>(9);
protected Expression()
{
table.Add("一", 1);
table.Add("二", 2);
table.Add("三", 3);
table.Add("四", 4);
table.Add("五", 5);
table.Add("六", 6);
table.Add("七", 7);
table.Add("八", 8);
table.Add("九", 9);
}
public virtual void Interpreter(Context context)
{
if (context.Statement.Length == 0)
{
return;
}
foreach (string key in table.Keys)
{
int value = table[key];
if (context.Statement.EndsWith(key + GetPostFix()))
{
context.Data += value * this.Multiplier();
context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());
}
if (context.Statement.EndsWith("零"))
{
context.Statement = context.Statement.Substring(0, context.Statement.Length - 1);
}
}
}
public abstract string GetPostFix();
public abstract int Multiplier();
//这个可以通用,但是对于个位数字例外,所以用虚方法
public virtual int GetLength()
{
return this.GetPostFix().Length + 1;
}
}
//个位表达式
public sealed class GeExpression : Expression
{
public override string GetPostFix()
{
return "";
}
public override int Multiplier()
{
return 1;
}
public override int GetLength()
{
return 1;
}
}
//十位表达式
public sealed class ShiExpression : Expression
{
public override string GetPostFix()
{
return "十";
}
public override int Multiplier()
{
return 10;
}
}
//百位表达式
public sealed class BaiExpression : Expression
{
public override string GetPostFix()
{
return "百";
}
public override int Multiplier()
{
return 100;
}
}
//千位表达式
public sealed class QianExpression : Expression
{
public override string GetPostFix()
{
return "千";
}
public override int Multiplier()
{
return 1000;
}
}
//万位表达式
public sealed class WanExpression : Expression
{
public override string GetPostFix()
{
return "万";
}
public override int Multiplier()
{
return 10000;
}
public override void Interpreter(Context context)
{
if (context.Statement.Length == 0)
{
return;
}
ArrayList tree = new ArrayList();
tree.Add(new GeExpression());
tree.Add(new ShiExpression());
tree.Add(new BaiExpression());
tree.Add(new QianExpression());
foreach (string key in table.Keys)
{
if (context.Statement.EndsWith(GetPostFix()))
{
int temp = context.Data;
context.Data = 0;
context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());
foreach (Expression exp in tree)
{
exp.Interpreter(context);
}
context.Data = temp + context.Data * this.Multiplier();
}
}
}
}
//亿位表达式
public sealed class YiExpression : Expression
{
public override string GetPostFix()
{
return "亿";
}
public override int Multiplier()
{
return 100000000;
}
public override void Interpreter(Context context)
{
ArrayList tree = new ArrayList();
tree.Add(new GeExpression());
tree.Add(new ShiExpression());
tree.Add(new BaiExpression());
tree.Add(new QianExpression());
foreach (string key in table.Keys)
{
if (context.Statement.EndsWith(GetPostFix()))
{
int temp = context.Data;
context.Data = 0;
context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());
foreach (Expression exp in tree)
{
exp.Interpreter(context);
}
context.Data = temp + context.Data * this.Multiplier();
}
}
}
}
//环境上下文
public sealed class Context
{
private string _statement;
private int _data;
public Context(string statement)
{
this._statement = statement;
}
public string Statement
{
get { return this._statement; }
set { this._statement = value; }
}
public int Data
{
get { return this._data; }
set { this._data = value; }
}
}