這篇文章主要講解了“.Net行為型設計模式之解釋器模式怎么實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“.Net行為型設計模式之解釋器模式怎么實現”吧!
在軟件構建過程中,如果某一特定領域的問題比較復雜,類似的模式不斷重復出現,如果使用普通的編程方式來實現將面臨非常頻繁的變化。在這種情況下,將特定領域的問題表達為某種語法規則下的句子,然后構建一個解釋器來解釋這樣的句子,從而達到解決問題的目的。
給定一個語言,定義它的文法的一種表示,并定義一種解釋器,這個解釋器使用該表示來解釋語言中的句子。 ——《設計模式》GoF

可以看出,在解釋器模式的結構圖有以下角色:
(1)、抽象表達式(AbstractExpression):定義解釋器的接口,約定解釋器的解釋操作。其中的Interpret接口,正如其名字那樣,它是專門用來解釋該解釋器所要實現的功能。
(2)、終結符表達式(Terminal Expression):實現了抽象表達式角色所要求的接口,主要是一個interpret()方法;文法中的每一個終結符都有一個具體終結表達式與之相對應。比如有一個簡單的公式R=R1+R2,在里面R1和R2就是終結符,對應的解析R1和R2的解釋器就是終結符表達式。
(3)、非終結符表達式(Nonterminal Expression):文法中的每一條規則都需要一個具體的非終結符表達式,非終結符表達式一般是文法中的運算符或者其他關鍵字,比如公式R=R1+R2中,“+”就是非終結符,解析“+”的解釋器就是一個非終結符表達式。
(4)、環境角色(Context):這個角色的任務一般是用來存放文法中各個終結符所對應的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息需要存放到環境角色中,很多情況下我們使用Map來充當環境角色就足夠了。
(5)、客戶端(Client):指的是使用解釋器的客戶端,通常在這里將按照語言的語法做的表達式轉換成使用解釋器對象描述的抽象語法樹,然后調用解釋操作。
在很多場合都需要把數字轉換成中文,我們就可以使用解釋器來實現該功能,把給定的數字解釋成符合語法規范的漢字表示法。實現代碼如下:
static void Main(string[] args)
{
string roman = "五億七千三百零二萬六千四百五十二";
//分解:((五)億)((七千)(三百)(零)(二)萬)
//((六千)(四百)(五十)(二))
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());
tree.Add(new YiExpression());
foreach (Expression exp in tree)
{
exp.Interpreter(context);
}
Console.Write(context.Data);
}
// 抽象表達式
public abstract class Expression
{
protected Dictionary<string, int> table = new Dictionary<string, int>(9);
protected Expression()
{
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 Interpreter(Context context)
{
if (context.Statement.Length == 0)
{
return;
}
foreach (string key in table.Keys)
{
int value = table[key];
if (context.Statement.EndsWith(key + GetPostFix()))
{
context.Data += value * this.Multiplier();
context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());
}
if (context.Statement.EndsWith("零"))
{
context.Statement = context.Statement.Substring(0, context.Statement.Length - 1);
}
}
}
public abstract string GetPostFix();
public abstract int Multiplier();
//這個可以通用,但是對于個位數字例外,所以用虛方法
public virtual int GetLength()
{
return this.GetPostFix().Length + 1;
}
}
//個位表達式
public sealed class GeExpression : Expression
{
public override string GetPostFix()
{
return "";
}
public override int Multiplier()
{
return 1;
}
public override int GetLength()
{
return 1;
}
}
//十位表達式
public sealed class ShiExpression : Expression
{
public override string GetPostFix()
{
return "十";
}
public override int Multiplier()
{
return 10;
}
}
//百位表達式
public sealed class BaiExpression : Expression
{
public override string GetPostFix()
{
return "百";
}
public override int Multiplier()
{
return 100;
}
}
//千位表達式
public sealed class QianExpression : Expression
{
public override string GetPostFix()
{
return "千";
}
public override int Multiplier()
{
return 1000;
}
}
//萬位表達式
public sealed class WanExpression : Expression
{
public override string GetPostFix()
{
return "萬";
}
public override int Multiplier()
{
return 10000;
}
public override void Interpreter(Context context)
{
if (context.Statement.Length == 0)
{
return;
}
ArrayList tree = new ArrayList();
tree.Add(new GeExpression());
tree.Add(new ShiExpression());
tree.Add(new BaiExpression());
tree.Add(new QianExpression());
foreach (string key in table.Keys)
{
if (context.Statement.EndsWith(GetPostFix()))
{
int temp = context.Data;
context.Data = 0;
context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());
foreach (Expression exp in tree)
{
exp.Interpreter(context);
}
context.Data = temp + context.Data * this.Multiplier();
}
}
}
}
//億位表達式
public sealed class YiExpression : Expression
{
public override string GetPostFix()
{
return "億";
}
public override int Multiplier()
{
return 100000000;
}
public override void Interpreter(Context context)
{
ArrayList tree = new ArrayList();
tree.Add(new GeExpression());
tree.Add(new ShiExpression());
tree.Add(new BaiExpression());
tree.Add(new QianExpression());
foreach (string key in table.Keys)
{
if (context.Statement.EndsWith(GetPostFix()))
{
int temp = context.Data;
context.Data = 0;
context.Statement = context.Statement.Substring(0, context.Statement.Length - this.GetLength());
foreach (Expression exp in tree)
{
exp.Interpreter(context);
}
context.Data = temp + context.Data * this.Multiplier();
}
}
}
}
//環境上下文
public sealed class Context
{
private string _statement;
private int _data;
public Context(string statement)
{
this._statement = statement;
}
public string Statement
{
get { return this._statement; }
set { this._statement = value; }
}
public int Data
{
get { return this._data; }
set { this._data = value; }
}
}使用Interpreter模式來表示文法規則,從而可以使用面向對象技巧方便地“擴展”文法。
Interpreter模式比較適合簡單的文法表示,對于復雜的文法表示,Interpreter模式會產生比較大的類層次結構,需要求助于語法分析生成器這樣的標準工具。
1】、易于改變和擴展文法。
2】、每一條文法規則都可以表示為一個類,因此可以方便地實現一個簡單的語言。
3】、實現文法較為容易。在抽象語法樹中每一個表達式節點類的實現方式都是相似的,這些類的代碼編寫都不會特別復雜,還可以通過一些工具自動生成節點類代碼。
4】、增加新的解釋表達式較為方便。如果用戶需要增加新的解釋表達式只需要對應增加一個新的終結符表達式或非終結符表達式類,原有表達式類代碼無須修改,符合“開閉原則”
1】、對于復雜文法難以維護。在解釋器模式中,每一條規則至少需要定義一個類,因此如果一個語言包含太多文法規則,類的個數將會急劇增加,導致系統難以管理和維護,此時可以考慮使用語法分析程序等方式來取代解釋器模式。
2】、執行效率較低。由于在解釋器模式中使用了大量的循環和遞歸調用,因此在解釋較為復雜的句子時其速度很慢,而且代碼的調試過程也比較麻煩。
Interpreter模式的應用場合是Interpreter模式應用中的難點,只有滿足“業務規則頻繁變化,且類似的模式不斷重復出現,并且容易抽象為語法規則的問題”才適合使用Interpreter模式。
1】、當一個語言需要解釋執行,并可以將該語言中的句子表示為一個抽象語法樹的時候,可以考慮使用解釋器模式(如XML文檔解釋、正則表達式等領域)
2】、一些重復出現的問題可以用一種簡單的語言來進行表達。
3】、一個語言的文法較為簡單.
4】、當執行效率不是關鍵和主要關心的問題時可考慮解釋器模式(注:高效的解釋器通常不是通過直接解釋抽象語法樹來實現的,而是需要將它們轉換成其他形式,使用解釋器模式的執行效率并不高。)
正則表達式就是一個典型的解釋器。ASP.NET中,把aspx文件轉化為dll時,會對html語言進行處理,這個處理過程也包含了解釋器的模式在里面。Interpreter模式其實有Composite模式的影子,但它們解決的問題是不一樣的。
感謝各位的閱讀,以上就是“.Net行為型設計模式之解釋器模式怎么實現”的內容了,經過本文的學習后,相信大家對.Net行為型設計模式之解釋器模式怎么實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。