设计模式C++实现--Interpreter模式
2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
解釋器模式
解釋器模式(Interpreter Pattern)提供了評估語言的語法或表達(dá)式的方式,它屬于行為型模式。這種模式實現(xiàn)了一個表達(dá)式接口,該接口解釋一個特定的上下文。這種模式被用在 SQL 解析、符號處理引擎等。
適用性:
在以下情況下可以考慮使用解釋器模式:
(1)?可以將一個需要解釋執(zhí)行的語言中的句子表示為一個抽象語法樹。
(2)??一些重復(fù)出現(xiàn)的問題可以用一種簡單的語言來進(jìn)行表達(dá)。
(3)?一個語言的文法較為簡單。
(4)?執(zhí)行效率不是關(guān)鍵問題。(注:高效的解釋器通常不是通過直接解釋抽象語法樹來實現(xiàn)的,而是需要將它們轉(zhuǎn)換成其他形式,使用解釋器模式的執(zhí)行效率并不高。)
優(yōu)缺點:
優(yōu)點:
(1)?易于改變和擴展文法。由于在解釋器模式中使用類來表示語言的文法規(guī)則,因此可以通過繼承等機制來改變或擴展文法。
(2)?每一條文法規(guī)則都可以表示為一個類,因此可以方便地實現(xiàn)一個簡單的語言。
(3)?實現(xiàn)文法較為容易。在抽象語法樹中每一個表達(dá)式節(jié)點類的實現(xiàn)方式都是相似的,這些類的代碼編寫都不會特別復(fù)雜,還可以通過一些工具自動生成節(jié)點類代碼。
(4)?增加新的解釋表達(dá)式較為方便。如果用戶需要增加新的解釋表達(dá)式只需要對應(yīng)增加一個新的終結(jié)符表達(dá)式或非終結(jié)符表達(dá)式類,原有表達(dá)式類代碼無須修改,符合“開閉原則”。
缺點:
(1)?對于復(fù)雜文法難以維護(hù)。在解釋器模式中,每一條規(guī)則至少需要定義一個類,因此如果一個語言包含太多文法規(guī)則,類的個數(shù)將會急劇增加,導(dǎo)致系統(tǒng)難以管理和維護(hù),此時可以考慮使用語法分析程序等方式來取代解釋器模式。
(2)?執(zhí)行效率較低。由于在解釋器模式中使用了大量的循環(huán)和遞歸調(diào)用,因此在解釋較為復(fù)雜的句子時其速度很慢,而且代碼的調(diào)試過程也比較麻煩。
總論:
盡量不要在重要模塊中使用解釋器模式,因為維護(hù)困難。在項目中,可以使用腳本語言來代替解釋器模式。
實現(xiàn)
? ? ? ? ? ? ??
抽象表達(dá)式角色(AbstractExpression):?聲明一個抽象的解釋操作,這個接口為所有具體表達(dá)式角色都要實現(xiàn)的。
終結(jié)符表達(dá)式角色(TerminalExpression):?實現(xiàn)與文法中的元素相關(guān)聯(lián)的解釋操作,通常一個解釋器模式中只有一個終結(jié)符表達(dá)式,但有多個實例對應(yīng)不同的終結(jié)符,
終結(jié)符就是語言中用到的基本元素,一般不能再被分解,如:?x?->?xa,?這里a是終結(jié)符,因為沒有別的規(guī)則可以把a變成別的符號,不過x可以變成別的符號,所以x是非終結(jié)符。
非終結(jié)符表達(dá)式角色(NonterminalExpression):?文法中的每條規(guī)則對應(yīng)于一個非終結(jié)表達(dá)式,?非終結(jié)表達(dá)式根據(jù)邏輯的復(fù)雜程度而增加,原則上每個文法規(guī)則都對應(yīng)一個非終結(jié)符表達(dá)式。
環(huán)境角色(Context):包含解釋器之外的一些全局信息。
步驟 1
創(chuàng)建上下文
class Contex{ private:map<string,int> _valueMap;public:int getValue(const string & key){return _valueMap[key];}void addValue( const string & key,int value){_valueMap.insert(pair<string,int>(key,value));} };?
步驟 2
創(chuàng)建抽象表達(dá)式接口
class AbstractExpression{ public:virtual ~ AbstractExpression(){}virtual int interpreter(Contex & contex) = 0; };?
步驟 3
創(chuàng)建兩種非終結(jié)表達(dá)式
class AddNonterminalExpression : public AbstractExpression{ private:AbstractExpression * _left;AbstractExpression * _right; public:AddNonterminalExpression(AbstractExpression * left,AbstractExpression * right):_left(left),_right(right){}int interpreter(Contex &contex) override {return _left->interpreter(contex) + _right->interpreter(contex);} };class SubNonterminalExpression : public AbstractExpression{ private:AbstractExpression * _left;AbstractExpression * _right; public:SubNonterminalExpression(AbstractExpression *_left, AbstractExpression *_right) : _left(_left), _right(_right) {}int interpreter(Contex &contex) override {return _left->interpreter(contex) - _right->interpreter(contex);} };?
步驟 4
創(chuàng)建終結(jié)表達(dá)式實現(xiàn)
class TerminalExpresiion : public AbstractExpression{ private:int _i;//終結(jié)符不能再切割 public:TerminalExpresiion(int i) : _i(i) {}int interpreter(Contex &contex) override {return _i;} };?
步驟 5
驗證
Contex contex;contex.addValue("a",1);contex.addValue("b",2);contex.addValue("c",3);AbstractExpression * sub_left = new TerminalExpresiion(contex.getValue("a"));AbstractExpression * sub_right = new TerminalExpresiion(contex.getValue("b"));AbstractExpression * subvalue = new SubNonterminalExpression(sub_left,sub_right);AbstractExpression * add_right = new TerminalExpresiion(contex.getValue("c"));AbstractExpression * addvalue = new AddNonterminalExpression(subvalue,add_right);std::cout << addvalue->interpreter(contex) << std::endl;delete(addvalue);delete(add_right);delete(subvalue);delete(sub_right);delete(sub_left);輸出結(jié)果
2?
轉(zhuǎn)載于:https://my.oschina.net/fileoptions/blog/1823480
總結(jié)
以上是生活随笔為你收集整理的设计模式C++实现--Interpreter模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android中ScrollView嵌套
- 下一篇: C++之引用的详解