设计模式之解释器模式
【原文转自】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
- /************************************************************************
- * description: 演奏内容
- * 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: 表达式类
- * 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);
- }
- }
- // 执行
- 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_
(2)客户端 InterpreterApp.cpp
- // InterpreterApp.cpp : 定义控制台应用程序的入口点。
- //
- #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;
- }
不积跬步无以至千里,不积小流无以成江河。