十八.行为型设计模式——Interpreter Pattern(解释器模式)

  • 定义

  给出一种语言,定义这种语言的文法的一种表示,定义一个解释器,用它来解释使用这种语言的句子。

  UML类图如下:

  

  其中类和对象之间的关系为:

  1.AbstractExpression(抽象表达式类):定义一个接口来执行解释操作。

  2.TerminalExpression(终结符表达式):实现文法中管理终结符的解释操作;文句中的每个终结符都需要一个实例。

  3.NonterminalExpression(非终结符表达式):文法中的每一条规则R::=R1R2....Rn都需要一个非终结符表达式类;维护每一条规则R1到Rn具有AbstractExpression接口实例;实现文法中关联非终结符的解释操作,采用递归的办法调用每一条规则R1到Rn的解释操作。

  4.Context(场景):包含解释器的所有全局信息。

  5.Client(客户应用程序):建造(或被给定)由这种语言表示的句子的抽象文法树,文法树由终结符表达式或者非终结符表达式的实例组成;调用文法树中的表达式实例的解释操作。

  典型应用的顺序图如下:

  

  客户先讲内容(context,又称上下文)分解生成多个非终结符号,再递归解释,直到所有终结符得到解释。

  • 实例1——中国金钱大写转换

  Interpreter模式的经典应用就是描述相同事情的不同语言转换。将中文的大写金额转换成阿拉伯数字表示就是一个例子。本例中没有用到nonTerminalExpression(非终结符)的类。

  

  

  

View Code
    class Context
{
private string input;
private int output;

public Context(string input)
{
this.input = input;
}

public string Input
{
get { return input; }
set { input = value; }
}

public int Output
{
get { return output; }
set { output = value; }
}
}

//抽象表达式类
abstract class Expression
{
public abstract string One();
public abstract string Four();
public abstract string Five();
public abstract string Nine();
public abstract int Multiplier();
public void Interpret(Context context)
{
if (context.Input.Length == 0)
return;
if (context.Input.StartsWith(Nine()))
{
context.Output
+= 9 * Multiplier();
context.Input
= context.Input.Substring(2);
}
else if (context.Input.StartsWith(Nine()))
{
context.Output
+= 9 * Multiplier();
context.Input
= context.Input.Substring(2);
}
else if (context.Input.StartsWith(Four()))
{
context.Output
+= 4 * Multiplier();
context.Input
= context.Input.Substring(2);
}
else if (context.Input.StartsWith(Five()))
{
context.Output
+= 5 * Multiplier();
context.Input
= context.Input.Substring(2);
}
else if (context.Input.StartsWith(One()))
{
context.Output
+= 1 * Multiplier();
context.Input
= context.Input.Substring(2);
}
}
}

//核对千位上的文字
class ThousandExpression : Expression
{
public override string One() { return "壹仟"; }
public override string Four() { return "肆仟"; }
public override string Five() { return "伍仟"; }
public override string Nine() { return "玖仟"; }
public override int Multiplier() { return 1000; }
}

//核对百位上的文字
class HundredExpression : Expression
{
public override string One() { return "壹百"; }
public override string Four() { return "肆百"; }
public override string Five() { return "伍百"; }
public override string Nine() { return "玖百"; }
public override int Multiplier() { return 100; }
}

//核对十位上的文字
class TenExpression : Expression
{
public override string One() { return "壹拾"; }
public override string Four() { return "肆拾"; }
public override string Five() { return "伍拾"; }
public override string Nine() { return "玖拾"; }
public override int Multiplier() { return 10; }
}

//核对个位上的文字
class OneExpression : Expression
{
public override string One() { return "壹圆"; }
public override string Four() { return "肆圆"; }
public override string Five() { return "伍圆"; }
public override string Nine() { return "玖圆"; }
public override int Multiplier() { return 1; }
}

class Program
{
static void Main(string[] args)
{
string chinese = "壹仟伍百玖拾伍圆";
Context context
= new Context(chinese);
ArrayList parse
= new ArrayList();
parse.Add(
new ThousandExpression());
parse.Add(
new HundredExpression());
parse.Add(
new TenExpression());
parse.Add(
new OneExpression());

foreach (Expression exp in parse)
{
exp.Interpret(context);
}

Console.Write(
"{0} = {1}", chinese, context.Output);
Console.Read();
}
}
  • 优势和缺陷:

  解释器模式的作用很强大,它使得改变和扩展文法变得容易,实现文法也变得简单明了,很多编译器,包括文本编辑器、网页浏览器及VRML都应用解释器模式。

  解释器模式的缺陷就是,因为文句会分析成树结构,解释器需要递归访问它,所以效率会受影响。这种情况开发人员会有所体会,编译整个工程源码耗费时间都比较长。

  • 应用情景:

  下面的情景很适合应用解释器模式:

  1.语言的文法需要扩展。

  2.程序效率不太重要。

posted on 2011-09-20 00:20  tLEE  阅读(650)  评论(0编辑  收藏  举报

导航