设计模式之解释器模式

【原文转自】http://blog.csdn.net/freshow/article/details/5772307

解释器模式(interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

解释器模式需要解决的是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。用了解释器模式,就意味着可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。

 

解释器模式不足的是,解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。

 

解释器模式(interpreter)结构图

 

 

 

实际应用

工程结构:

(1)音乐解释器 playContext.h、expression.h、note.h、scale.h、speed.h

(2)客户端       InterpreterApp.cpp

 

(1)音乐解释器 

playContext.h

 

  1. /************************************************************************ 
  2.  * description: 演奏内容 
  3.  * remark:       
  4. ************************************************************************/  
  5. #ifndef _PLAY_CONTEXT_H_  
  6. #define _PLAY_CONTEXT_H_  
  7. #include <string>  
  8. #include <iostream>  
  9. using namespace std;  
  10. class playContext  
  11. {  
  12. public:  
  13.     string getPlayText()  
  14.     {  
  15.         return m_strText;  
  16.     }  
  17.     void setPlayText(const string& strText)  
  18.     {  
  19.         m_strText = strText;  
  20.     }  
  21. private:  
  22.     string m_strText;  
  23. };  
  24. #endif// _PLAY_CONTEXT_H_  
 

expression.h

  1. /************************************************************************ 
  2.  * description: 表达式类 
  3.  * remark:       
  4. ************************************************************************/  
  5. #ifndef _EXPRESSION_H_  
  6. #define _EXPRESSION_H_  
  7. #include "playContext.h"  
  8. class expression  
  9. {  
  10. public:  
  11.     // 解释器  
  12.     void interpret(playContext& PlayContext)  
  13.     {  
  14.         if (PlayContext.getPlayText().empty())  
  15.         {  
  16.             return;  
  17.         }  
  18.         else  
  19.         {  
  20.             string strPlayKey = PlayContext.getPlayText().substr(0, 1);  
  21.             string strtemp = PlayContext.getPlayText().substr(2);  
  22.             PlayContext.setPlayText(strtemp);  
  23.               
  24.             size_t nPos = PlayContext.getPlayText().find(" ");  
  25.             string strPlayValue = PlayContext.getPlayText().substr(0, nPos);  
  26.             int    nPlayValue = atoi(strPlayValue.c_str());  
  27.             nPos = PlayContext.getPlayText().find(" ");  
  28.             PlayContext.setPlayText(PlayContext.getPlayText().substr(nPos + 1));  
  29.             excute(strPlayKey, nPlayValue);  
  30.         }  
  31.     }  
  32.     // 执行  
  33.     virtual void excute(string& strKey, const int nValue) = 0;  
  34. private:  
  35. };  
  36. #endif// _EXPRESSION_H_  
 

 

note.h

  1. /************************************************************************ 
  2.  * description: 音符类 
  3.  * remark:       
  4. ************************************************************************/  
  5. #ifndef _NOTE_H_  
  6. #define _NOTE_H_  
  7. #include "expression.h"  
  8. class note : public expression  
  9. {  
  10. public:  
  11.     virtual void excute(string& strKey, const int nValue)  
  12.     {  
  13.         char szKey[2];  
  14.         strncpy(szKey, strKey.c_str(), strKey.length());  
  15.         string strNote;  
  16.         switch (szKey[0])  
  17.         {  
  18.         case 'C':  
  19.             strNote = "1";  
  20.             break;  
  21.         case 'D':  
  22.             strNote = "2";  
  23.             break;  
  24.         case 'E':  
  25.             strNote = "3";  
  26.             break;  
  27.         case 'F':  
  28.             strNote = "4";  
  29.             break;  
  30.         case 'G':  
  31.             strNote = "5";  
  32.             break;  
  33.         case 'A':  
  34.             strNote = "6";  
  35.             break;  
  36.         case 'B':  
  37.             strNote = "7";  
  38.             break;  
  39.         default:  
  40.             strNote = "error";  
  41.             break;  
  42.         }  
  43.         cout << strNote << " ";  
  44.     }  
  45. };  
  46. #endif// _NOTE_H_  
 

 

scale.h

  1. /************************************************************************ 
  2.  * description: 音阶类 
  3.  * remark:       
  4. ************************************************************************/  
  5. #ifndef _SCALE_H_  
  6. #define _SCALE_H_  
  7. #include "expression.h"  
  8. class scale : public expression  
  9. {  
  10. public:  
  11.     virtual void excute(string& strKey, const int nValue)  
  12.     {  
  13.         string strScale;  
  14.         switch (nValue)  
  15.         {  
  16.         case 1:  
  17.             strScale = "低音";  
  18.             break;  
  19.         case 2:  
  20.             strScale = "中音";  
  21.             break;  
  22.         case 3:  
  23.             strScale = "高音";  
  24.             break;  
  25.         default:  
  26.             strScale = "error";  
  27.             break;  
  28.         }  
  29.         cout << strScale << " ";  
  30.     }  
  31. private:  
  32. };  
  33. #endif// _SCALE_H_  
 

 

speed.h

  1. #ifndef _SPEED_H_  
  2. #define _SPEED_H_  
  3. #include "expression.h"  
  4. class speed : public expression  
  5. {  
  6. public:  
  7.     virtual void excute(string& strKey, const int nValue)  
  8.     {  
  9.         string strSpeed;  
  10.         if (nValue < 3)  
  11.         {  
  12.             strSpeed = "快速";  
  13.         }  
  14.         else if (nValue >= 6)  
  15.         {  
  16.             strSpeed = "慢速";  
  17.         }  
  18.         else  
  19.         {  
  20.             strSpeed = "中速";  
  21.         }  
  22.         cout << strSpeed << " ";  
  23.     }  
  24. };  
  25. #endif// _SPEED_H_  
 

 

(2)客户端       InterpreterApp.cpp

  1. // InterpreterApp.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3. #include "stdafx.h"  
  4. #include "note.h"  
  5. #include "scale.h"  
  6. #include "speed.h"  
  7. #include "playContext.h"  
  8. int _tmain(int argc, _TCHAR* argv[])  
  9. {  
  10.     playContext context;  
  11.     cout << "Music:";  
  12.       
  13.     context.setPlayText("T 2 O 2 E 3 G 5 G 5 ");  
  14.     expression* expressObj = NULL;  
  15.       
  16.     while (!context.getPlayText().empty())  
  17.     {  
  18.         string strSep = context.getPlayText().substr(0, 1);  
  19.         char szKey[2];  
  20.         strncpy(szKey, strSep.c_str(), strSep.length());  
  21.         switch (szKey[0])  
  22.         {  
  23.         case 'O':  
  24.             expressObj = new scale();  
  25.             break;  
  26.         case 'T':  
  27.             expressObj = new speed();  
  28.             break;  
  29.         case 'C':  
  30.         case 'D':  
  31.         case 'E':  
  32.         case 'F':  
  33.         case 'G':  
  34.         case 'A':  
  35.         case 'B':  
  36.         case 'P':  
  37.             expressObj = new note();  
  38.             break;  
  39.         default:  
  40.             break;  
  41.         }  
  42.         if (NULL != expressObj)  
  43.         {  
  44.             expressObj->interpret(context);  
  45.         }  
  46.     }  
  47.     system("pause");  
  48.     return 0;  
  49. }  
 



posted @ 2012-08-29 22:25  $逝水无痕$  阅读(215)  评论(0编辑  收藏  举报