设计模式16:Interpreter Pattern(解释者模式)
本文翻译自:http://www.dofactory.com/Patterns/PatternInterpreter.aspx
Define:Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
一、解释者模式概念
针对某一编程语言,为其语法定义一定的描述语言和解释器,解释器利用描述语言去解释该编程语言中的所有语法。
二、UML类图
三、参与者
该模式的类/对象参与者包括:
- AbstractExpression (描述)
- 为执行operation()声明一个接口
- TerminalExpression ( ThousandExpression, HundredExpression, TenExpression, OneExpression )
- 在语法中使用终止符实现一个operation解释器
- 在语句中要求所有终止符需要一个实例
- NonterminalExpression ( 不使用 )
- one such class is required for every rule R ::= R1R2...Rn in the grammar
- maintains instance variables of type AbstractExpression for each of the symbols R1 through Rn.
- implements an Interpret operation for nonterminal symbols in the grammar. Interpret typically calls itself recursively on the variables representing R1 through Rn.
- Context (Context)
- 所有全局解释器的内容信息
- Client (InterpreterApp)
- builds (or is given) an abstract syntax tree representing a particular sentence in the language that the grammar defines. The abstract syntax tree is assembled from instances of the NonterminalExpression and TerminalExpression classes
- invokes the Interpret operation
四、示例代码
以下结构性的代码描述解释器模式,即利用一个定义好的语法,为进程解析声明提供解释器。
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
- namespace Interpreter_Pattern
- {
- /// <summary>
- /// MainApp startup class for Structural
- /// Interpreter Design Pattern.
- /// </summary>
- class MainApp
- {
- /// <summary>
- /// Entry point into console application.
- /// </summary>
- static void Main()
- {
- Context context = new Context();
- // Usually a tree
- ArrayList list = new ArrayList();
- // Populate 'abstract syntax tree'
- list.Add(new TerminalExpression());
- list.Add(new NonterminalExpression());
- list.Add(new TerminalExpression());
- list.Add(new TerminalExpression());
- // Interpret
- foreach (AbstractExpression exp in list)
- {
- exp.Interpret(context);
- }
- // Wait for user
- Console.ReadKey();
- }
- }
- /// <summary>
- /// The 'Context' class
- /// </summary>
- class Context
- {
- }
- /// <summary>
- /// The 'AbstractExpression' abstract class
- /// </summary>
- abstract class AbstractExpression
- {
- public abstract void Interpret(Context context);
- }
- /// <summary>
- /// The 'TerminalExpression' class
- /// </summary>
- class TerminalExpression : AbstractExpression
- {
- public override void Interpret(Context context)
- {
- Console.WriteLine("Called Terminal.Interpret()");
- }
- }
- /// <summary>
- /// The 'NonterminalExpression' class
- /// </summary>
- class NonterminalExpression : AbstractExpression
- {
- public override void Interpret(Context context)
- {
- Console.WriteLine("Called Nonterminal.Interpret()");
- }
- }
- }
另外一个实例即利用解释器模式来实现如何将罗马数字跟十进制的转换,代码如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
- namespace Interpreter_Pattern
- {
- class MainApp
- {
- /// <summary>
- /// Entry point into console application.
- /// </summary>
- static void Main()
- {
- string roman = "MCMXXVIII";
- Context context = new Context(roman);
- // Build the 'parse tree'
- List<Expression> tree = new List<Expression>();
- tree.Add(new ThousandExpression());
- tree.Add(new HundredExpression());
- tree.Add(new TenExpression());
- tree.Add(new OneExpression());
- // Interpret
- foreach (Expression exp in tree)
- {
- exp.Interpret(context);
- }
- Console.WriteLine("{0} = {1}",
- roman, context.Output);
- // Wait for user
- Console.ReadKey();
- }
- }
- /// <summary>
- /// The 'Context' class
- /// </summary>
- class Context
- {
- private string _input;
- private int _output;
- // Constructor
- public Context(string input)
- {
- this._input = input;
- }
- // Gets or sets input
- public string Input
- {
- get { return _input; }
- set { _input = value; }
- }
- // Gets or sets output
- public int Output
- {
- get { return _output; }
- set { _output = value; }
- }
- }
- /// <summary>
- /// The 'AbstractExpression' class
- /// </summary>
- abstract class Expression
- {
- 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(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(1);
- }
- while (context.Input.StartsWith(One()))
- {
- context.Output += (1 * Multiplier());
- context.Input = context.Input.Substring(1);
- }
- }
- public abstract string One();
- public abstract string Four();
- public abstract string Five();
- public abstract string Nine();
- public abstract int Multiplier();
- }
- /// <summary>
- /// A 'TerminalExpression' class
- /// <remarks>
- /// Thousand checks for the Roman Numeral M
- /// </remarks>
- /// </summary>
- class ThousandExpression : Expression
- {
- public override string One() { return "M"; }
- public override string Four() { return " "; }
- public override string Five() { return " "; }
- public override string Nine() { return " "; }
- public override int Multiplier() { return 1000; }
- }
- /// <summary>
- /// A 'TerminalExpression' class
- /// <remarks>
- /// Hundred checks C, CD, D or CM
- /// </remarks>
- /// </summary>
- class HundredExpression : Expression
- {
- public override string One() { return "C"; }
- public override string Four() { return "CD"; }
- public override string Five() { return "D"; }
- public override string Nine() { return "CM"; }
- public override int Multiplier() { return 100; }
- }
- /// <summary>
- /// A 'TerminalExpression' class
- /// <remarks>
- /// Ten checks for X, XL, L and XC
- /// </remarks>
- /// </summary>
- class TenExpression : Expression
- {
- public override string One() { return "X"; }
- public override string Four() { return "XL"; }
- public override string Five() { return "L"; }
- public override string Nine() { return "XC"; }
- public override int Multiplier() { return 10; }
- }
- /// <summary>
- /// A 'TerminalExpression' class
- /// <remarks>
- /// One checks for I, II, III, IV, V, VI, VI, VII, VIII, IX
- /// </remarks>
- /// </summary>
- class OneExpression : Expression
- {
- public override string One() { return "I"; }
- public override string Four() { return "IV"; }
- public override string Five() { return "V"; }
- public override string Nine() { return "IX"; }
- public override int Multiplier() { return 1; }
- }
- }
乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern)
乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern)
作者:webabcd
介绍
给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
示例
有一个Message实体类,某个类对它的操作有Get()方法。现在要求用具有某一规则的中文语法来执行这个操作。
MessageModel
using System;
using System.Collections.Generic;
using System.Text;
namespace Pattern.Interpreter
{
/// <summary>
/// Message实体类
/// </summary>
public class MessageModel
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="msg">Message内容</param>
/// <param name="pt">Message发布时间</param>
public MessageModel(string msg, DateTime pt)
{
this._message = msg;
this._publishTime = pt;
}
private string _message;
/// <summary>
/// Message内容
/// </summary>
public string Message
{
get { return _message; }
set { _message = value; }
}
private DateTime _publishTime;
/// <summary>
/// Message发布时间
/// </summary>
public DateTime PublishTime
{
get { return _publishTime; }
set { _publishTime = value; }
}
}
}
SqlMessage
using System;
using System.Collections.Generic;
using System.Text;
namespace Pattern.Interpreter
{
/// <summary>
/// Sql方式操作Message
/// </summary>
public class SqlMessage
{
/// <summary>
/// 获取Message
/// </summary>
/// <returns></returns>
public static List<MessageModel> Get()
{
List<MessageModel> l = new List<MessageModel>();
l.Add(new MessageModel("SQL方式获取Message", DateTime.Now));
return l;
}
}
}
Context
using System;
using System.Collections.Generic;
using System.Text;
namespace Pattern.Interpreter
{
/// <summary>
/// Context
/// </summary>
public class Context
{
private string _input;
private string _output;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="input">输入内容</param>
public Context(string input)
{
this._input = input;
}
/// <summary>
/// 输入内容
/// </summary>
public string Input
{
get { return _input; }
set { _input = value; }
}
/// <summary>
/// 输出内容
/// </summary>
public string Output
{
get { return _output; }
set { _output = value; }
}
}
}
AbstractExpression
using System;
using System.Collections.Generic;
using System.Text;
namespace Pattern.Interpreter
{
/// <summary>
/// 抽象公式(AbstractExpression)
/// </summary>
public abstract class AbstractExpression
{
/// <summary>
/// 解释Context的方法
/// </summary>
/// <param name="context">context</param>
public void Interpret(Context context)
{
if (String.IsNullOrEmpty(context.Input))
{
return;
}
context.Output += GetCSharp(context.Input);
}
/// <summary>
/// 获得输入内容所对应的C#代码
/// </summary>
/// <param name="source">source</param>
/// <returns></returns>
private string GetCSharp(string source)
{
string csharp = "";
string word = "";
// 从输入内容中取得要解释的词
word = GetWord(source);
// 从字典中找到word所对应的C#代码
GetDictionary().TryGetValue(word, out csharp);
return csharp;
}
/// <summary>
/// 从输入内容中取得要解释的词
/// </summary>
/// <param name="source">source</param>
/// <returns></returns>
public abstract string GetWord(string source);
/// <summary>
/// 获取字典
/// </summary>
/// <returns></returns>
public abstract Dictionary<string, string> GetDictionary();
}
}
DatabaseExpression
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Pattern.Interpreter
{
/// <summary>
/// 终端公式(TerminalExpression)分析与数据库相关的
/// </summary>
public class DatabaseExpression : AbstractExpression
{
/// <summary>
/// 从输入内容中取得要解释的词
/// </summary>
/// <param name="source">source</param>
/// <returns></returns>
public override string GetWord(string source)
{
MatchCollection mc;
Regex r = new Regex(@"\{(.*)\}");
mc = r.Matches(source);
return mc[0].Groups[1].Value;
}
/// <summary>
/// 获取与数据库相关的字典
/// </summary>
/// <returns></returns>
public override Dictionary<string, string> GetDictionary()
{
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("数据库", "Sql");
return d;
}
}
}
ObjectExpression
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Pattern.Interpreter
{
/// <summary>
/// 终端公式(TerminalExpression)分析与对象相关的
/// </summary>
public class ObjectExpression : AbstractExpression
{
/// <summary>
/// 从输入内容中取得要解释的词
/// </summary>
/// <param name="source">source</param>
/// <returns></returns>
public override string GetWord(string source)
{
MatchCollection mc;
Regex r = new Regex(@"\[(.*)\]");
mc = r.Matches(source);
return mc[0].Groups[1].Value;
}
/// <summary>
/// 获取与对象相关的字典
/// </summary>
/// <returns></returns>
public override Dictionary<string, string> GetDictionary()
{
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("信息", "Message");
return d;
}
}
}
MethodExpression
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Pattern.Interpreter
{
/// <summary>
/// 终端公式(TerminalExpression)分析与方法相关的
/// </summary>
public class MethodExpression : AbstractExpression
{
/// <summary>
/// 从输入内容中取得要解释的词
/// </summary>
/// <param name="source">source</param>
/// <returns></returns>
public override string GetWord(string source)
{
MatchCollection mc;
Regex r = new Regex(@"\((.*)\)");
mc = r.Matches(source);
return mc[0].Groups[1].Value;
}
/// <summary>
/// 获取与方法相关的字典
/// </summary>
/// <returns></returns>
public override Dictionary<string, string> GetDictionary()
{
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("获取", ".Get()");
return d;
}
}
}
client
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.CSharp;
using System.Reflection;
using System.Text;
using System.Collections.Generic;
using Pattern.Interpreter;
public partial class Interpreter : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string chinese = "{数据库}[信息](获取)";
Context context = new Context(chinese);
List<AbstractExpression> l = new List<AbstractExpression>();
l.Add(new DatabaseExpression());
l.Add(new ObjectExpression());
l.Add(new MethodExpression());
foreach (AbstractExpression exp in l)
{
exp.Interpret(context);
}
Assembly assembly = Assembly.Load("Pattern.Interpreter");
MethodInfo method = assembly.GetType("Pattern.Interpreter." + context.Output.Split('.')[0]).GetMethod(context.Output.Split('.')[1].Replace("()", ""));
object obj = method.Invoke(null, null);
List<MessageModel> m = (List<MessageModel>)obj;
Response.Write("中文语法:" + chinese);
Response.Write("<br />");
Response.Write("解释后的C#代码:" + context.Output);
Response.Write("<br />");
Response.Write("执行结果:" + m[0].Message + " " + m[0].PublishTime.ToString());
}
}
运行结果
中文语法:{数据库}[信息](获取)
解释后的C#代码:SqlMessage.Get()
执行结果:SQL方式获取Message 2007-5-1 8:48:07
参考
http://www.dofactory.com/Patterns/PatternInterpreter.aspx
OK
[源码下载]
示例代码:
using System;
using System.Collections.Generic;
using System.Text;
namespace InterpreterPattern
{
/// <summary>
/// 上下文(环境)角色类:包含解释器之外的一些全局信息。
/// </summary>
public class Context
{
/// <summary>
/// 变量对象集合
/// </summary>
private IDictionary<CharExpression, int> charExpressions = new Dictionary<CharExpression, int>();
private string _input;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="input">输入内容</param>
public Context(string input)
{
this._input = input;
}
/// <summary>
/// 输入内容
/// </summary>
public string Input
{
get { return _input; }
set { _input = value; }
}
/// <summary>
/// 设置变量的值
/// </summary>
/// <param name="charExpression">变量</param>
/// <param name="number">值</param>
public void SetValue(CharExpression charExpression, int number)
{
if (!charExpressions.ContainsKey(charExpression))
{
charExpressions.Add(charExpression, number);
}
else
{
charExpressions[charExpression] = number;
}
}
/// <summary>
/// 获得变量的值
/// </summary>
/// <param name="charExpression">变量</param>
/// <returns>值</returns>
public int GetValue(CharExpression charExpression)
{
int number = 0;
if (charExpressions.ContainsKey(charExpression))
{
number = charExpressions[charExpression];
}
return number;
}
}
/// <summary>
/// 抽象表达式类:声明一个抽象的解释操作,抽象语法树中所有的节点共享该抽象类。
/// </summary>
public abstract class AbstractExpression
{
/// <summary>
/// 解释操作,完成具体的语法分析
/// </summary>
/// <param name="context">上下文</param>
/// <returns>结果</returns>
public abstract int Interpret(Context context);
}
/// <summary>
/// 终结符表达式(TerminalExpression)角色类一:实现与文法中的终结符相关联的解释操作,一个句子中的每个终结符需要该类的一个实例 。
/// 该类处理数字。
/// </summary>
public class NumnerExpression : AbstractExpression
{
private int number;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="number">数字</param>
public NumnerExpression(int number)
{
this.number = number;
}
/// <summary>
/// 解释操作,完成具体的语法分析
/// </summary>
/// <param name="context">上下文</param>
/// <returns>结果</returns>
public override int Interpret(Context context)
{
return number;
}
}
/// <summary>
/// 终结符表达式(TerminalExpression)角色类二:实现与文法中的终结符相关联的解释操作,一个句子中的每个终结符需要该类的一个实例 。
/// 该类处理字符。
/// </summary>
public class CharExpression : AbstractExpression
{
/// <summary>
/// 解释操作,完成具体的语法分析
/// </summary>
/// <param name="context">上下文</param>
/// <returns>结果</returns>
public override int Interpret(Context context)
{
return context.GetValue(this);
}
}
/// <summary>
/// 非终结符表达式(NonterminalExpression)角色类一:文法中的每条规则R::=R1R2…Rn都需要一个非终结符表带式角色,对于从R1到Rn的每个符号都维护一个抽象表达式角色的实例变量
/// 解释一般要递归地调用表示从R1到Rn的那些对象的解释操作
/// 该类处理加号。
/// </summary>
public class AddExpression : AbstractExpression
{
private AbstractExpression _left;
private AbstractExpression _right;
public AddExpression(AbstractExpression left, AbstractExpression right)
{
this._left = left;
this._right = right;
}
/// <summary>
/// 左部分
/// </summary>
public AbstractExpression Left
{
get { return _left; }
set { _left = value; }
}
/// <summary>
/// 右部分
/// </summary>
public AbstractExpression Right
{
get { return _right; }
set { _right = value; }
}
/// <summary>
/// 解释操作,完成具体的语法分析
/// </summary>
/// <param name="context">上下文</param>
/// <returns>结果</returns>
public override int Interpret(Context context)
{
return _left.Interpret(context) + _right.Interpret(context);
}
}
/// <summary>
/// 非终结符表达式(NonterminalExpression)角色类二:文法中的每条规则R::=R1R2…Rn都需要一个非终结符表带式角色,对于从R1到Rn的每个符号都维护一个抽象表达式角色的实例变量
/// 解释一般要递归地调用表示从R1到Rn的那些对象的解释操作
/// 该类处理减号。
/// </summary>
public class SubtractExpression : AbstractExpression
{
private AbstractExpression _left;
private AbstractExpression _right;
public SubtractExpression(AbstractExpression left, AbstractExpression right)
{
this._left = left;
this._right = right;
}
/// <summary>
/// 左部分
/// </summary>
public AbstractExpression Left
{
get { return _left; }
set { _left = value; }
}
/// <summary>
/// 右部分
/// </summary>
public AbstractExpression Right
{
get { return _right; }
set { _right = value; }
}
/// <summary>
/// 解释操作,完成具体的语法分析
/// </summary>
/// <param name="context">上下文</param>
/// <returns>结果</returns>
public override int Interpret(Context context)
{
return _left.Interpret(context) - _right.Interpret(context);
}
}
class Program
{
static void Main(string[] args)
{
string input = "a-(b+2)";
Context context = new Context(input);
NumnerExpression num = new NumnerExpression(2);
CharExpression a = new CharExpression();
CharExpression b = new CharExpression();
//赋值
context.SetValue(a, 5);
context.SetValue(b, 1);
AbstractExpression expression = new SubtractExpression(a, new AddExpression(b, num));
Console.WriteLine("结果:{0}", expression.Interpret(context));
Console.ReadLine();
}
}
}