深入解析C++設(shè)計(jì)模式編程中解釋器模式的運(yùn)用
解釋器模式(interpreter),給定一個(gè)語(yǔ)言,定義它的文法的一種表示,并定義一個(gè)解釋器,這個(gè)解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。
解釋器模式需要解決的是,如果一種特定類型的問題發(fā)生的頻率足夠高,那么可能就值得將該問題的各個(gè)實(shí)例表述為一個(gè)簡(jiǎn)單語(yǔ)言中的句子。這樣就可以構(gòu)建一個(gè)解釋器,該解釋器通過解釋這些句子來(lái)解決該問題。當(dāng)有一個(gè)語(yǔ)言需要解釋執(zhí)行,并且你可將該語(yǔ)言中的句子表示為一個(gè)抽象語(yǔ)法樹時(shí),可使用解釋器模式。用了解釋器模式,就意味著可以很容易地改變和擴(kuò)展文法,因?yàn)樵撃J绞褂妙悂?lái)表示文法規(guī)則,你可使用繼承來(lái)改變或擴(kuò)展該文法。也比較容易實(shí)現(xiàn)文法,因?yàn)槎x抽象語(yǔ)法樹中各個(gè)節(jié)點(diǎn)的類的實(shí)現(xiàn)大體類似,這些類都易于直接編寫。
結(jié)構(gòu)圖:

實(shí)例:
音樂解釋器
playContext.h
/************************************************************************
* description: 演奏內(nèi)容
* remark:
************************************************************************/
#ifndef _PLAY_CONTEXT_H_
#define _PLAY_CONTEXT_H_
#include <string>
#include <iostream>
using namespace std;
class playContext
{
public:
string getPlayText()
{
return m_strText;
}
void setPlayText(const string& strText)
{
m_strText = strText;
}
private:
string m_strText;
};
#endif// _PLAY_CONTEXT_H_
expression.h
/************************************************************************
* description: 表達(dá)式類
* remark:
************************************************************************/
#ifndef _EXPRESSION_H_
#define _EXPRESSION_H_
#include "playContext.h"
class expression
{
public:
// 解釋器
void interpret(playContext& PlayContext)
{
if (PlayContext.getPlayText().empty())
{
return;
}
else
{
string strPlayKey = PlayContext.getPlayText().substr(0, 1);
string strtemp = PlayContext.getPlayText().substr(2);
PlayContext.setPlayText(strtemp);
size_t nPos = PlayContext.getPlayText().find(" ");
string strPlayValue = PlayContext.getPlayText().substr(0, nPos);
int nPlayValue = atoi(strPlayValue.c_str());
nPos = PlayContext.getPlayText().find(" ");
PlayContext.setPlayText(PlayContext.getPlayText().substr(nPos + 1));
excute(strPlayKey, nPlayValue);
}
}
// 執(zhí)行
virtual void excute(string& strKey, const int nValue) = 0;
private:
};
#endif// _EXPRESSION_H_
note.h
/************************************************************************
* description: 音符類
* remark:
************************************************************************/
#ifndef _NOTE_H_
#define _NOTE_H_
#include "expression.h"
class note : public expression
{
public:
virtual void excute(string& strKey, const int nValue)
{
char szKey[2];
strncpy(szKey, strKey.c_str(), strKey.length());
string strNote;
switch (szKey[0])
{
case 'C':
strNote = "1";
break;
case 'D':
strNote = "2";
break;
case 'E':
strNote = "3";
break;
case 'F':
strNote = "4";
break;
case 'G':
strNote = "5";
break;
case 'A':
strNote = "6";
break;
case 'B':
strNote = "7";
break;
default:
strNote = "error";
break;
}
cout << strNote << " ";
}
};
#endif// _NOTE_H_
scale.h
/************************************************************************
* description: 音階類
* remark:
************************************************************************/
#ifndef _SCALE_H_
#define _SCALE_H_
#include "expression.h"
class scale : public expression
{
public:
virtual void excute(string& strKey, const int nValue)
{
string strScale;
switch (nValue)
{
case 1:
strScale = "低音";
break;
case 2:
strScale = "中音";
break;
case 3:
strScale = "高音";
break;
default:
strScale = "error";
break;
}
cout << strScale << " ";
}
private:
};
#endif// _SCALE_H_
speed.h
#ifndef _SPEED_H_
#define _SPEED_H_
#include "expression.h"
class speed : public expression
{
public:
virtual void excute(string& strKey, const int nValue)
{
string strSpeed;
if (nValue < 3)
{
strSpeed = "快速";
}
else if (nValue >= 6)
{
strSpeed = "慢速";
}
else
{
strSpeed = "中速";
}
cout << strSpeed << " ";
}
};
#endif// _SPEED_H_
客戶端: InterpreterApp.cpp
// InterpreterApp.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
//
#include "stdafx.h"
#include "note.h"
#include "scale.h"
#include "speed.h"
#include "playContext.h"
int _tmain(int argc, _TCHAR* argv[])
{
playContext context;
cout << "Music:";
context.setPlayText("T 2 O 2 E 3 G 5 G 5 ");
expression* expressObj = NULL;
while (!context.getPlayText().empty())
{
string strSep = context.getPlayText().substr(0, 1);
char szKey[2];
strncpy(szKey, strSep.c_str(), strSep.length());
switch (szKey[0])
{
case 'O':
expressObj = new scale();
break;
case 'T':
expressObj = new speed();
break;
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'A':
case 'B':
case 'P':
expressObj = new note();
break;
default:
break;
}
if (NULL != expressObj)
{
expressObj->interpret(context);
}
}
system("pause");
return 0;
}
不足之處
解釋器模式不足的是,解釋器模式為文法中的每一條規(guī)則至少定義了一個(gè)類,因此包含許多規(guī)則的文法可能難以管理和維護(hù)。建議當(dāng)文法非常復(fù)雜時(shí),使用其他的技術(shù)如語(yǔ)法分析程序或編譯器生成器來(lái)處理。
適用場(chǎng)景
- 當(dāng)有一個(gè)語(yǔ)言需要解釋執(zhí)行, 并且你可將該語(yǔ)言中的句子表示為一個(gè)抽象語(yǔ)法樹時(shí),可使用解釋器模式。而當(dāng)存在以下情況時(shí)該模式效果最好:
- 該文法簡(jiǎn)單對(duì)于復(fù)雜的文法, 文法的類層次變得龐大而無(wú)法管理。此時(shí)語(yǔ)法分析程序生成器這樣的工具是更好的選擇。它們無(wú)需構(gòu)建抽象語(yǔ)法樹即可解釋表達(dá)式, 這樣可以節(jié)省空間而且還可能節(jié)省時(shí)間。
- 效率不是一個(gè)關(guān)鍵問題最高效的解釋器通常不是通過直接解釋語(yǔ)法分析樹實(shí)現(xiàn)的, 而是首先將它們轉(zhuǎn)換成另一種形式。例如,正則表達(dá)式通常被轉(zhuǎn)換成狀態(tài)機(jī)。但即使在這種情況下, 轉(zhuǎn)換器仍可用解釋器模式實(shí)現(xiàn), 該模式仍是有用的。
- 實(shí)例講解C++設(shè)計(jì)模式編程中State狀態(tài)模式的運(yùn)用場(chǎng)景
- 解析C++編程中如何使用設(shè)計(jì)模式中的狀態(tài)模式結(jié)構(gòu)
- 詳解C++設(shè)計(jì)模式編程中對(duì)訪問者模式的運(yùn)用
- C++設(shè)計(jì)模式編程之Flyweight享元模式結(jié)構(gòu)詳解
- 詳解設(shè)計(jì)模式中的中介者模式在C++編程中的運(yùn)用
- 詳解C++設(shè)計(jì)模式編程中責(zé)任鏈模式的應(yīng)用
- 詳解設(shè)計(jì)模式中的Command命令模式及相關(guān)C++實(shí)現(xiàn)
- C++設(shè)計(jì)模式編程中使用Bridge橋接模式的完全攻略
- 設(shè)計(jì)模式中的備忘錄模式解析及相關(guān)C++實(shí)例應(yīng)用
- C++設(shè)計(jì)模式編程中簡(jiǎn)單工廠與工廠方法模式的實(shí)例對(duì)比
相關(guān)文章
QT+Quick實(shí)現(xiàn)自定義組件的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何利用QT+Quick實(shí)現(xiàn)自定義組件(按鈕、下拉菜單等),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-11-11
C語(yǔ)言中l(wèi)seek()函數(shù)和fseek()函數(shù)的使用詳解
這篇文章主要介紹了C語(yǔ)言中l(wèi)seek()函數(shù)和fseek()函數(shù)的使用詳解,是C語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-08-08
C++11并發(fā)編程關(guān)于原子操作atomic的代碼示例
今天小編就為大家分享一篇關(guān)于C++11并發(fā)編程關(guān)于原子操作atomic的代碼示例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
C++ Eigen庫(kù)實(shí)現(xiàn)最小二乘擬合的示例代碼
Eigen 是一個(gè)線性算術(shù)的 C++ 模板庫(kù),功能強(qiáng)大、快速、優(yōu)雅以及支持多平臺(tái),本文主要為大家介紹了C++利用Eigen庫(kù)實(shí)現(xiàn)最小二乘擬合的示例代碼,希望對(duì)大家有所幫助2023-07-07
C++ Boost shared_ptr共享指針詳細(xì)講解
shared_ptr是一個(gè)標(biāo)準(zhǔn)的共享所有權(quán)的智能指針,允許多個(gè)指針指向同一個(gè)對(duì)象,定義在memory文件中,命名空間為std,這篇文章主要介紹了C++ shared_ptr使用,需要的朋友可以參考下2022-11-11

