行为型模式:Interpreter 解释器模式

      行为型模式:Interpreter 解释器模式

1、动机(Motivation)
  1)在软件构建过程当中,若是某一特定领域的问题比较复杂,相似的模式不断重复出现,若是使用普通的编程方式来实现将面临很是频繁的变化。
  2)在这种状况下,将特定领域的问题表达为某种语法规则下的句子,而后构建一个解释器来解释这样的句子,从而达到解决问题的目的。
 
2、意图(Intent)
  给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。
                                                                          ——《设计模式》GoF
 
3、实例:将中文数字转换为数学的数字
using System;
using System.Collections;
using System.Collections.Generic;算法

//客户
public class MainApp
{
  public static void Main()
  {
    string roman = "一亿二千三百五十七万六千四百五十二" //==>123576452
   
    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());
     
    foreach (Expression exp in tree)
    {
      exp.Interpret(context);
    }
    Console.WriteLine("{0} = {1}", roman, context.Data);
  }
}编程

//字符串上下文信息:保存没有处理的字符串信息
public class Context
{
  private string statement;
  private int data;
 
  public Context(string statement)
  {
    this.statement = statement;
  }
 
  public string Statement
  {
    get
    {
      return statement;
    }
    set
    {
      statement = value;
    }
  }
 
  public int Data
  {
    get
    {
      return data;
    }
    set
    {
      data = value;
    }
  }
}设计模式

//抽象类:解释器
public abstract class Expression
{
  //数据字典:保存中文数字一到九
  protected Dictionary<string, int> table = new Dictionary<string, int>(9);
  //构造器:初始化数据字典,将中文数字一到九保存到数据字典变量中
  public Expression()
  {
    //对于恒定不变的没有必要封装,只用一个数据结构保存就好了
    if (table.count < 9)
    {
      table.Clear();
      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 Interpret(Context context)
  {
    if (context.Statement.Length == 0)
    {
      return;
    }
    foreach (string key in table.Keys)
    {
      if (context.Statement.EndsWith(key + this.GetPostfix()))
      {
        context.Data += table[key] * this.Mulitiplier();
        context.Statement = context.Statement.Substring(0, context.Statement.Length - 1 - this.GetPostfix().Length);
      }
      else if (context.Statement.EndsWith("零"))
      {
        context.Statement = context.Statement.Substring(0, context.Statement.Length - 1);
      }
    }
  }
 
  //表达式的后缀是以什么表示的(10、百....)
  public abstract string GetPostfix();
  //表达式的数量级
  public abstract int Mulitiplier();
}数据结构

//个位数的解释器
public class GeExpression : Expression
{
  public override string GetPostfix()
  {
    return "";
  }
  public override int Multiplier()
  {
    return 1;
  }
}ide

//后缀是十的解释器
public class ShiExpression : Expression
{
  public override string GetPostfix()
  {
    return "十";
  }
  public override int Multiplier()
  {
    return 10;
  }
}工具

//后缀是百的解释器
public class BaiExpression : Expression
{
  public override string GetPostfix()
  {
    return "百";
  }
  public override int Multiplier()
  {
    return 100;
  }
}性能

//后缀是千的解释器
public class QianExpression : Expression
{
  public override string GetPostfix()
  {
    return "千";
  }
  public override int Multiplier()
  {
    return 1000;
  }
}this

//后缀是万的解释器
public class WanExpression : Expression
{
  public override string GetPostfix()
  {
    return "万";
  }
  public override int Multiplier()
  {
    return 10000;
  }
 
  public override void Interpret(Context context)
  {
    if (context.Statement.Length == 0)
    {
      return;
    }
   
    if (context.Statement.EndsWith(this.GetPostfix())
    {
      ArrayList tree = new ArrayList();
      tree.Clear();
      tree.Add(new GeExpression());
      tree.Add(new ShiExpression());
      tree.Add(new BaiExpression());
      tree.Add(new QianExpression());
     
      int temp = context.Data;
      context.Data = 0;
      context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());
       
      foreach (Expression exp in tree)
      {
        exp.Interpret(context);
      }
      context.Data = temp + this.Multiplier() * context.Data;
    }
  }
}设计

  分析:使用Interpreter模式来将中文数字转换为数学数字的好处是能够应对中文数字的变化,虽然能够用一很好的算法将中文转化为数字,解释器的扩展性能比较好,若是出现亿、兆的状况,能够写出两个类(YiExpression、ZhaoExpression)来继承Expression类,而其余地方的代码都不变化。对象

4、Interpreter模式的几个要点   1)Interpreter模式的应用场合是Interpreter模式应用中的难点,只有知足“业务规则频繁变化,且相似的模式不断重复出现,而且容易抽象为语法规则的问题”才适合使用Interpreter模式。   2)使用Interpreter模式来表示文法规则,从而能够使用面向对象技巧来方便地“扩展”文法。   3)Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,须要求助于语法分析生成器这样的标准工具。

相关文章
相关标签/搜索