求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
.NET 设计模式学习笔记Interpreter(解释器模式)
 

作者:spring yang,发布于2011-12-23

 

概述

在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。

意图

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

结构图

角色说明:

AbstractExpression:

- 声明一个抽象的Interpret方法,抽象语法树中所有的节点都必须实现该抽象方法。

TerminalExpression:

- 实现和语法中末端符号相关的Interpret方法。

- 在每个句子的末端符号中均需要一个TerminalExpression实例。

NonterminalExpression:

另外一个实现了AbstractExpression 接口的类,用来处理语法树中非末端节点的语法。它含有下一个AbstractExpression(s)的引用,调用它每个子节点的Interpret方法。

Context:

Interpreter方法所需要的信息的容器,该信息对Interpreter而言全局可见。充当几个AbstractExpresssion 实例之间的通讯频道。

PatternClient:

构建或者接收一个抽象语法书的实例。对于一个特定的句子而言,语法树往往由若干个TerminalExpressions 和 NonterminalExpression组成。PatterClient在合适的context下,调用Interpret方法。

生活中的例子

在日常生活中英汉辞典的作用就是把中文翻译成英文或者是把英文翻译成中文,它的实现原理就是词典库里先把对应的中文和英文存在数据库表里,然后根据你输入的内容来匹配出相应的结果出来.

示例用例图

在公司里,借款单申请需要高管来审批,而高管又不会上班时间都坐在电脑面前,公司就有个系统,员工的借款申请都会通过手机短信方式来提示高管,高管可以通过回复短信来审批单据,高管一般都很懒,不愿回复太多的字,只能回复Y或y来表示同意,N或n表示拒绝,用四位标识码代替借款申请单号,用例图如下:

代码设计

先创建ReplyContent.cs:

/// <summary>

/// 回复内容

/// </summary>

public class ReplyContent

{

  private string _ReplyText;

  public string ReplyText

  {

    get { return _ReplyText; }

    set { _ReplyText = value; }

  }

}

再创建InterPreter.cs:

public abstract class InterPreter

{

  public string ConvertContent(ReplyContent content)

  {

    if (content.ReplyText.Length == 0)

    return "请按规则回复审批短信.";

    return Excute(content.ReplyText);

  }

  public abstract string Excute(string key);

}

再创建Approve.cs:

public class Approve : InterPreter

{

  public override string Excute(string key)

  {

    if (key == "Y" || key == "y")

    {

      return "同意";

    }

    else if (key == "N" || key == "n")

    {

      return "拒绝";

    }

    else

    {

      return "回复内容有误,请重新回复.";

    }

  }

}

再创建DocumentNum.cs:

public class DocumentNum : InterPreter

{

  public Dictionary<string, string> OddNum

  {

    get

    {

      Dictionary<string, string> OddID = new Dictionary<string, string>();

      OddID.Add("0001", "123890890892345");

      OddID.Add("0002", "123456717012345");

      OddID.Add("0003", "123456669012345");

      OddID.Add("0004", "123423444012345");

      OddID.Add("0005", "123467845345345");

      OddID.Add("0006", "123231234564345");

      OddID.Add("0007", "128797897867745");

      return OddID;

    }

  }

  public override string Excute(string key)

  {

    string value = null;

    if (OddNum.TryGetValue(key, out value))

    {

      return value;

    }

    else

    {

      return "没找到对应的单号.";

    }

  }

}

再创建ReplyClient.cs:

public class ReplyClient

{

  public static string ApplyContent(string ReplayValue)

  {

    ReplyContent content = new ReplyContent();

    string approvevalue = ReplayValue.Substring(0, 1);

    string OddIDvalue = ReplayValue.Substring(1, 4);

    string result = string.Empty;

    InterPreter expression = new Approve();

    content.ReplyText = approvevalue;

    result = string.Format("你{0}", expression.ConvertContent(content));

    expression = new DocumentNum();

    content.ReplyText = OddIDvalue;

    result += string.Format("单号是{0}的申请.\n", expression.ConvertContent(content));

    return result;

  }

}

最后再调用:

public partial class Run : Form

{

  public Run()

  {

    InitializeComponent();

  }

  private void btnRun_Click(object sender, EventArgs e)

  {

    //-------------------------------------

    rtbResult.AppendText(ReplyClient.ApplyContent("Y0001"));

    rtbResult.AppendText(ReplyClient.ApplyContent("y0002"));

    rtbResult.AppendText(ReplyClient.ApplyContent("N0003"));

    rtbResult.AppendText(ReplyClient.ApplyContent("n0004"));

  }

}

结果如下图:

实现要点

1.Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易抽象为语法规则 的问题”才适合使用Interpreter模式。

2.使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法。

3.Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interperter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具。

适用性

1.Interpreter模式的应用场合是interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式。

总结

效率不是一个Interpreter关心的关键问题。最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。例如:正则表达式通常被转换成状态机。但即使在这种情况下,如果效率不是一个关键问题,转换器仍可用Interpreter模式实现,该模式仍是有用的。


相关文章

企业架构、TOGAF与ArchiMate概览
架构师之路-如何做好业务建模?
大型网站电商网站架构案例和技术架构的示例
完整的Archimate视点指南(包括示例)
相关文档

数据中台技术架构方法论与实践
适用ArchiMate、EA 和 iSpace进行企业架构建模
Zachman企业架构框架简介
企业架构让SOA落地
相关课程

云平台与微服务架构设计
中台战略、中台建设与数字商业
亿级用户高并发、高可用系统架构
高可用分布式架构设计与实践
 
分享到
 
 
     


重构-使代码更简洁优美
Visitor Parttern
由表及里看模式
设计模式随笔系列
深入浅出设计模式-介绍
.NET中的设计模式
更多...   

相关培训课程

J2EE设计模式和性能调优
应用模式设计Java企业级应用
设计模式原理与应用
J2EE设计模式指南
单元测试+重构+设计模式
设计模式及其CSharp实现


某电力公司 设计模式原理
蓝拓扑 设计模式原理及应用
卫星导航 UML & OOAD
汤森路透研发中心 UML& OOAD
中达电通 设计模式原理
西门子 嵌入式设计模式
更多...