《大話設計模式》--其實你不懂老闆的心--直譯器模式(27)
阿新 • • 發佈:2019-01-28
I:給定一個語言,定義它的文法的一種表示,並定義一個直譯器,這個直譯器使用該表示來解釋語言中的句子。
如果一種特定型別的問題發生的頻率足夠高,那麼可能就值得將該問題的各個例項表述為一個簡單語言中的句子。這樣就可以構建一個直譯器,該直譯器通過解釋這些句子來解決該問題。
好處:當有一個語言需要解釋執行,並且你可將該語言中的句子表示為一個抽象語法樹時,可使用直譯器模式。
容易的改變和擴充套件方法,因為該模式使用類來表示文法規則,你可使用繼承來改變或擴充套件該文法。也可以較容易實現文法,因為定義抽象語法樹中各個節點的類的實現大體類似,這些類都易於直接編寫。
不足:直譯器模式為文法中的每一條規則至少定義了一個類,因此包含許多規則的文法可能難以管理和維護。建議當文法非常複雜時,使用其他的技術如語法分析程式或編譯器生成器來處理。
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 = 0d; double.TryParse(context.PlayText.Substring(0, context.PlayText.IndexOf(" ")), out playValue); context.PlayText = context.PlayText.Substring(context.PlayText.IndexOf(" ") + 1); Execute(playKey, playValue); } } public abstract void Execute(string playKey, double playValue); }
class Note:Expression { public override void Execute(string playKey, double playValue) { string note = ""; switch (playKey) { 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.WriteLine(string.Format("{0}", note)); } }
class Scale:Expression
{
public override void Execute(string playKey, double playValue)
{
string scale = "";
int val = 1;
int.TryParse(playValue.ToString(), out val);
switch (val)
{
case 1:
scale = "低音";
break;
case 2:
scale = "中音";
break;
case 3:
scale = "高音";
break;
}
Console.WriteLine(string.Format("{0}", scale));
}
}
class Speed:Expression
{
public override void Execute(string playKey, double playValue)
{
string speed;
if (playValue < 500)
speed = "快速";
else if (playValue >= 1000)
speed = "慢速";
else
speed = "中速";
Console.WriteLine(string.Format("{0}", speed));
}
}
客戶端程式碼:
PlayContext context = new PlayContext();
Console.WriteLine("上海灘:");
context.PlayText = "T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 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 "T":
expression = new Speed();
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 ex)
{
Console.WriteLine(ex.Message);
}