行爲型模式: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模式會產生比較大的類層次結構,須要求助於語法分析生成器這樣的標準工具。

相關文章
相關標籤/搜索