天天看點

解釋器模式-interpreter

解釋器模式(interpreter),給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。

解釋器模式需要解決的是,如是一種特定類型的問題發生的頻率足夠高,那麼可能就值得将該問題的各個執行個體表述為一個簡單語言中的句子。這樣就可以建構一個解釋器,該解釋器通過解釋這些句子來解決問題。

象正規表達式,浏覽器等都可能了解成這種應用。

解釋器模式結構圖:

解釋器模式-interpreter

代碼實作

AbstractExpression 抽象表達式,聲明一個抽象的解釋操作,這個接口為抽象文法樹中所有的節點所共享

abstract class AbstractExpression

{

 public abstract void Interpret(Context context);

}

TerminalExpression(終結符表達式),實作與文法中的終結符相關聯的解釋操作,實作抽象表達式中所要求的接口,主要是一個interpret()方法,文法中每一個終結符都有一個具體終結表達式與之對應。

class TerminalExpression : AbstractExpression

{

 public override void Interpret(Context context)

 {

  Console.WriteLine("終端解釋器");

 }

}

NonterminalExpression非終結符表達式,為文法中的非終結符實作解釋操作。對文法中每一條規則的R1,R2...都需要一個具體的非終結符表達式式類。通過實作抽象表達式的interpret()方法實作解釋操作,解釋操作以遞歸方式調用上面所提到的代表R1,R2...中各個符号的執行個體變量。

class NonterminalExpress : AbstractExpression

{

 public override void Interpret(Context context)

 {

  Console.WriteLine("非終端解釋器");

 }

}

Context 包含解釋器之外的一些全局資訊

class Context

{

 private string input;

 public string Input

 {

  get { return input;}

  set { input = value;}

 }

 private string output;

 public string Output

 {

  get { return output;

  set { output = value;}

 }

}

---用戶端代碼---

static void Main(string[] args)

{

 Context context = new Context();

 IList<AbstractExpression> list = new <AbstractExpression>();

 list.Add(new TerminalExpression());

 list.Add(new NonterminalExpression());

 list.Add(new TerminalExpression());

 list.Add(new TerminalExpression());

 foreach(AbstractExpression exp in list)

 {

  exp.Interpret(context);

 }

 Console.Read();

}

當有一個語言需要解釋執行,并且你可将該語言中的句子表示為一個抽象文法樹時,可使用解釋器模式。

好處:可以很容易地改變和擴充文法,因為該模式使用類來表示文法規則,你可使用繼承來改變為或擴充文法。也比較容易實作文法,因為定義抽象文法樹中各個節點的類的實作大體類似,都易于直接編寫。

音樂解釋器實作

代碼結構圖

解釋器模式-interpreter
演奏内容類context
 class PlayContext
 {
  private string text;
  public string PlayText
  {
   get { return text;}
   set { text = value;}
  }
 }
表達式類
 abstract class Expression
 {
  //解釋器
  public void Interpret(PlayContext context)
  {
   if(context.PlayText.Length ==0)
   {
    return;
   }
   else
   {
    string playKey = context.PlayText.Substring(0,1);
    context.PlayText = context.PlayText.Substring(2);
    double playValue = Convert.ToDouble(context.PlayText.Substring(0,context.PlayText.Indexof(" ")));
    //獲得key和value後将其從演奏文本中移除
    context.PlayText = context.PlayText.Substring(context.PlayText.IndexOf(" ")+1);
  
    Excute(playKey,playValue);
   }
   
  }
  //執行,不同的文法子類,有不同的執行處理
  public abstract void Excute(string key,double value);
 }//音符類
 class Note : Expression
 {
  public override void Excute(string key,double value)
  {
   string note="";
   switch(key)
   {
    case "C":
     note ="1";
     break;
    case "D":
     note ="2";
     break;
    case "E":
     note ="3";
     break;
    case "F":
     note ="4";
     break;
    case "G":
     note ="5";
     break;
    case "A":
     note ="6";
     break;
    case "B":
     note ="7";
     break;
   }
   Console.Write("{0}",note);
  }
 }class Scale : Expression
 {
  public override void Excute(string key,double value)
  {
   string scale="";
   switch(Convert.ToInt32(value))
   {
    case 1:
     scale ="低音";
     break;
    case 2:
     scale ="中音";
     break;
    case 3:
     scale ="高音";
     break;
    
   }
   Console.Write("{0}",scale);
  } 
 }---用戶端代碼---
 static void Main(string[] args)
 {
  PlayContext context = new PlayContext();
  Conosle.WriteLine("音樂");
  context.PlayText="O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 ";
  Expression expression = null;
  try
  {
   while(context.PlayText.Length >0)
   {
    string str = context.PlayText.Substring(0,1);
    switch(str)
    {
     case "O":
      expression = new Scale();
      break;
     case "C":
     case "D":
     case "E":
     case "F":
     case "G":
     case "A":
     case "B":
     case "P":
      expression = new Note();
      break;    }
    expression.Interpret(context);
   }
  }
  catch(Exception ex1)
  {
   Console.WriteLine("ex1.Message);
  }
  Console.Read();
 }