我所理解的設計模式(C++實現)——解譯器模式(Interpreter Pattern)

來源:互聯網
上載者:User
概述:

        未來機器智能化已然成為趨勢,現在手機都能聽懂英語和普通話,那我大中華幾萬種方言的被智能化也許也是趨勢,我們的方言雖然和普通話相似,但是還是不一樣的。這可能需要一個新的文法分析器來協助我們。

我們的解譯器模式就是描述了如何為簡單的語言定義一個文法,如何在該語言中表示一個句子,以及如何解釋這些句子。

但是解釋一門自然語言是複雜的過程,我們以加減運算為例子來詳細解釋解譯器模式。

類圖和執行個體:

抽象運算式角色(AbstractExpression): 聲明一個抽象的解釋操作,這個介面為所有具體運算式角色都要實現的。
終結符運算式角色(TerminalExpression): 實現與文法中的元素相關聯的解釋操作,通常一個解譯器模式中只有一個終結符運算式,但有多個執行個體對應不同的終結符,
終結符就是語言中用到的基本元素,一般不能再被分解,如: x -> xa, 這裡a是終結符,因為沒有別的規則可以把a變成別的符號,不過x可以變成別的符號,所以x是非終結符。
非終結符運算式角色(NonterminalExpression): 文法中的每條規則對應於一個非終結運算式, 非終結運算式根據邏輯的複雜程度而增加,原則上每個文法規則都對應一個非終結符運算式。
環境角色(Context):包含解譯器之外的一些全域資訊。

執行個體:

#include <iostream>  #include <map>  #include <string>   using namespace std;  class Context{private:map<string, int> valueMap;public:void addValue(string key,int value){       valueMap.insert(std::pair<string,int>(key,value));}int getValue(string key){return valueMap[key];}};class AbstractExpression{public : virtual int interpreter(Context context) = 0;};class AddNonterminalExpression : public AbstractExpression{private :AbstractExpression *left;AbstractExpression *right;public:AddNonterminalExpression(AbstractExpression *left, AbstractExpression *right){this->left = left;this->right = right;}int interpreter(Context context){return this->left->interpreter(context) + this->right->interpreter(context);}};class SubtractNonterminalExpression : public AbstractExpression{private :AbstractExpression *left;AbstractExpression *right;public:SubtractNonterminalExpression(AbstractExpression *left, AbstractExpression *right){this->left = left;this->right = right;}int interpreter(Context context){return this->left->interpreter(context) - this->right->interpreter(context);}};class TerminalExpression : public AbstractExpression{private :int i;public :TerminalExpression(int i){this->i = i;}int interpreter(Context context){return this->i;}};int main(){  //a-b+cContext context;context.addValue("a", 7);context.addValue("b", 8);context.addValue("c", 2);SubtractNonterminalExpression *subtractValue = new SubtractNonterminalExpression(new TerminalExpression(context.getValue("a")), new TerminalExpression(context.getValue("b")));AddNonterminalExpression *addValue = new AddNonterminalExpression(subtractValue, new TerminalExpression(context.getValue("c")));cout<< addValue->interpreter(context);return 0;  }  
適用性:

在以下情況下可以考慮使用解譯器模式:

(1) 可以將一個需要解釋執行的語言中的句子表示為一個抽象文法樹。

(2)  一些重複出現的問題可以用一種簡單的語言來進行表達。

(3) 一個語言的文法較為簡單。

(4) 執行效率不是關鍵問題。(註:高效的解譯器通常不是通過直接解釋抽象文法樹來實現的,而是需要將它們轉換成其他形式,使用解譯器模式的執行效率並不高。)

優缺點:優點:

(1) 易於改變和擴充文法。由於在解譯器模式中使用類來表示語言的文法規則,因此可以通過繼承等機制來改變或擴充文法。

(2) 每一條文法規則都可以表示為一個類,因此可以方便地實現一個簡單的語言。

(3) 實現文法較為容易。在抽象文法樹中每一個運算式節點類的實現方式都是相似的,這些類的代碼編寫都不會特別複雜,還可以通過一些工具自動產生節點類代碼。

(4) 增加新的解釋運算式較為方便。如果使用者需要增加新的解釋運算式只需要對應增加一個新的終結符運算式或非終結符運算式類,原有運算式類代碼無須修改,符合“開閉原則”。

缺點:

(1) 對於複雜文法難以維護。在解譯器模式中,每一條規則至少需要定義一個類,因此如果一個語言套件含太多文法規則,類的個數將會急劇增加,導致系統難以管理和維護,此時可以考慮使用文法剖析器等方式來取代解譯器模式。

(2) 執行效率較低。由於在解譯器模式中使用了大量的迴圈和遞迴調用,因此在解釋較為複雜的句子時其速度很慢,而且代碼的調試過程也比較麻煩。

總論:

盡量不要在重要模組中使用解譯器模式,因為維護困難。在項目中,可以使用指令碼語言來代替解譯器模式。

LCL_data原創於CSDN.NET【http://blog.csdn.net/lcl_data/article/details/9259905】

其他設計模式請參考:我所理解的設計模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.