解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
接下来描述一个将中文数字转化为阿拉伯数字的例子
先定义一个抽象表达式
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)
{
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 override int GetLength()
{
return 1;
}
}
//亿位表达式
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 override int GetLength()
{
return 1;
}
}
环境上下文
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; }
}
}
调用
class Program
{
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);
Console.Read();
}
}
结果
573026452
类图
优点与缺点
解释器模式的优点:
- 可扩展性比较好,灵活。
- 增加了新的解释表达式的方式。
- 易于实现文法。
解释器模式的缺点:
- 执行效率比较低,可利用场景比较少。
- 对于复杂的文法比较难维护。
本文主要借鉴了《Gof设计模式》与C#设计模式之二十三解释器模式(Interpreter Pattern)【行为型】