目錄
- 定義與特點
- 結構與實作
- 模式的結構
- 模式的實作
- 應用場景
- 擴展:Expression 運算式樹和Flee
在軟體開發中,會遇到有些問題多次重復出現,而且有一定的相似性和規律性,如果將它們歸納成一種簡單的語言,那么這些問題實體將是該語言的一些句子,這樣就可以用“編譯原理”中的解釋器模式來實作了,
雖然使用解釋器模式的實體不是很多,但對于滿足以上特點,且對運行效率要求不是很高的應用實體,如果用解釋器模式來實作,其效果是非常好的,本文將介紹其作業原理與使用方法,
定義與特點
解釋器(Interpreter)模式的定義:給分析物件定義一個語言,并定義該語言的文法表示,再設計一個決議器來解釋語言中的句子,也就是說,用編譯語言的方式來分析應用中的實體,這種模式實作了文法運算式處理的介面,該介面解釋一個特定的背景關系,
這里提到的文法和句子的概念同編譯原理中的描述相同,“文法”指語言的語法規則,而“句子”是語言集中的元素,例如,漢語中的句子有很多,“我是中國人”是其中的一個句子,可以用一棵語法樹來直觀地描述語言中的句子,
解釋器模式是一種類行為型模式,其主要優點如下:
- 擴展性好:由于在解釋器模式中使用類來表示語言的文法規則,因此可以通過繼承等機制來改變或擴展文法,
- 容易實作:在語法樹中的每個運算式節點類都是相似的,所以實作其文法較為容易,
解釋器模式的主要缺點如下:
- 執行效率較低:解釋器模式中通常使用大量的回圈和遞回呼叫,當要解釋的句子較復雜時,其運行速度很慢,且代碼的除錯程序也比較麻煩,
- 會引起類膨脹:解釋器模式中的每條規則至少需要定義一個類,當包含的文法規則很多時,類的個數將急劇增加,導致系統難以管理與維護,
- 可應用的場景比較少:在軟體開發中,需要定義語言文法的應用實體非常少,所以這種模式很少被使用到,
結構與實作
解釋器模式常用于對簡單語言的編譯或分析實體中,為了掌握好它的結構與實作,必須先了解編譯原理中的“文法、句子、語法樹”等相關概念,
文法:文法是用于描述語言的語法結構的形式規則,沒有規矩不成方圓,任何事情都要有規則,語言也一樣,不管它是機器語言還是自然語言,都有它自己的文法規則,例如,中文中的“句子”的文法如下:
〈句子〉::=〈主語〉〈謂語〉〈賓語〉
〈主語〉::=〈代詞〉|〈名詞〉
〈謂語〉::=〈動詞〉
〈賓語〉::=〈代詞〉|〈名詞〉
〈代詞〉你|我|他
〈名詞〉7大學生I筱霞I英語
〈動詞〉::=是|學習
注:這里的符號“::=”表示“定義為”的意思,用“〈”和“〉”括住的是非終結符,沒有括住的是終結符,
句子:句子是語言的基本單位,是語言集中的一個元素,它由終結符構成,能由“文法”推匯出,例如,上述文法可以推出“我是大學生”,所以它是句子,
語法樹:語法樹是句子結構的一種樹型表示,它代表了句子的推導結果,它有利于理解句子語法結構的層次,下圖所示是“我是大學生”的語法樹:

有了以上基礎知識,現在來介紹解釋器模式的結構就簡單了,解釋器模式的結構與組合模式相似,不過其包含的組成元素比組合模式多,而且組合模式是物件結構型模式,而解釋器模式是類行為型模式,
模式的結構
解釋器模式包含以下主要角色:
- 抽象運算式(Abstract Expression)角色:定義解釋器的介面,約定解釋器的解釋操作,主要包含解釋方法 Interpret(),
- 終結符運算式(Terminal Expression)角色:是抽象運算式的子類,用來實作文法中與終結符相關的操作,文法中的每一個終結符都有一個具體終結運算式與之相對應,
- 非終結符運算式(Nonterminal Expression)角色:也是抽象運算式的子類,用來實作文法中與非終結符相關的操作,文法中的每條規則都對應于一個非終結符運算式,
- 環境(Context)角色:通常包含各個解釋器需要的資料或是公共的功能,一般用來傳遞被所有解釋器共享的資料,后面的解釋器可以從這里獲取這些值,
- 客戶端(Client):主要任務是將需要分析的句子或運算式轉換成使用解釋器物件描述的抽象語法樹,然后呼叫解釋器的解釋方法,當然也可以通過環境角色間接訪問解釋器的解釋方法,
解釋器模式的結構圖如圖所示:

模式的實作
解釋器模式實作的關鍵是定義文法規則、設計終結符類與非終結符類、畫出結構圖,必要時構建語法樹,其代碼結構如下:
//抽象運算式類
public interface IAbstractExpression
{
Object Interpret(String info); //解釋方法
}
//終結符運算式類
public class TerminalExpression : IAbstractExpression
{
public Object Interpret(String info)
{
//對終結符運算式的處理
}
}
//非終結符運算式類
public class NonterminalExpression : IAbstractExpression
{
private IAbstractExpression exp1;
private IAbstractExpression exp2;
public Object Interpret(String info)
{
//非對終結符運算式的處理
}
}
//環境類
public class Context
{
private IAbstractExpression exp;
public Context()
{
//資料初始化
}
public void Operation(String info)
{
//呼叫相關運算式類的解釋方法
}
}
應用場景
前面介紹了解釋器模式的結構與特點,下面分析它的應用場景:
- 當語言的文法較為簡單,且執行效率不是關鍵問題時,
- 當問題重復出現,且可以用一種簡單的語言來進行表達時,
- 當一個語言需要解釋執行,并且語言中的句子可以表示為一個抽象語法樹的時候,如 XML 檔案解釋,
注意:解釋器模式在實際的軟體開發中使用比較少,因為它會引起效率、性能以及維護等問題,如果碰到對運算式的解釋,在 C# 中可以用 Expression類 或 Flee 等來設計,
擴展:Expression 運算式樹和Flee
在專案開發中,如果要對資料運算式進行分析與計算,無須再用解釋器模式進行設計了,C# 提供了 Expression 運算式樹,也可以使用 Flee 等開源類別庫,它們可以解釋一些復雜的文法,功能強大,使用簡單,
Flee是.NET框架的運算式決議器和評估器,它使用自定義編譯器,強型別運算式語言和輕量級代碼生成器將運算式直接編譯為IL,
github鏈接:Flee
使用說明:https://github.com/mparlak/Flee/wiki
使用NuGet安裝Flee,創建和評估運算式的示例代碼如下:
// Set the culture of Flee's parser
CultureInfo ci = new CultureInfo("fr-FR");
ExpressionContext context = new ExpressionContext();
context.ParseCulture = ci
context.Imports.AddType(typeof(Math));
// Create an expression that uses numbers in the culture's format
IDynamicExpression e = context.CompileDynamic("round(100,75; 1)");
object result = e.Evaluate();
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/1077.html
標籤:設計模式
上一篇:狀態模式
下一篇:設計模式-策略模式
