23种设计模式(23)--Interpreter模式

来源:互联网 发布:建筑模型动画软件 编辑:程序博客网 时间:2024/05/21 15:26

平心而论,之前的22个设计模式大多都是比较常见的,几乎做任何项目都有使用的价值。然而这个Interpreter模式则不然,其适用范围较小。正如其名,此模式大多用来解释一些(自定义的)独特语法,例如某些游戏开发引擎中读取XML文件,或是WindowsPhone开发中的XAML文件,都是使用此模式来进行的。与其说是一种模式,不如说是一种具有通用规范的行为更为准确。

一个简单的例子:一份密码电报,需要通过特定的解读顺序以及某些关键字来解读,才可以获取其内容,而此模式即是大抵如此。

【核心】通过解释器来解释某种特定语法。

UML图:



这里有必要解释一下UML图:


Interpret方法即是解释器本身的行为。

TerminalExpression是终止符表达式,例如A◎B这个表达式中的A,B即是终止符。

NonterminalExpression是非终止符表达式,上式中的◎符号即为非终止符。

Context就是上下文啦,也就是需要被解释的东西。


【大致思路】

string类型的加密电报作为Context传入NonterminalExpression中,

其被后者通过Interpreter方法进行解释,

并输出密码。


Interpreter.h

[cpp] view plain copy
  1. #ifndef _INTERPRETER_H_  
  2. #define _INTERPRETER_H_  
  3. #include<string>  
  4.   
  5. typedef std::string Context ;  
  6.   
  7. class AbstractExpression  
  8. {  
  9. public:  
  10.     AbstractExpression(){}  
  11.     ~AbstractExpression(){}  
  12.   
  13.     virtual void Interpreter(const Context& context)=0;  
  14. };  
  15.   
  16. class TerminalExpression : public AbstractExpression  
  17. {  
  18. public:  
  19.     TerminalExpression(char kc);  
  20.     ~TerminalExpression(){}  
  21.   
  22.     virtual void Interpreter(const Context& context);  
  23.   
  24. private:  
  25.     char keyChar;  
  26. };  
  27.   
  28. class NonterminalExpression : public AbstractExpression  
  29. {  
  30. public:  
  31.     NonterminalExpression(AbstractExpression* ae);  
  32.     ~NonterminalExpression(){}  
  33.   
  34.     virtual void Interpreter(const Context& context);  
  35.   
  36. private:  
  37.     AbstractExpression* terminalExpression;  
  38. };  
  39.   
  40. #endif  

Interpreter.cpp

[cpp] view plain copy
  1. #include "Interpreter.h"  
  2. #include<iostream>  
  3.   
  4. TerminalExpression::TerminalExpression(char kc)  
  5. {  
  6.     keyChar = kc;  
  7. }  
  8.   
  9. void TerminalExpression::Interpreter(const Context& context)  
  10. {  
  11.     int length = 0;  
  12.     while (context[length] != '\0')  
  13.     {  
  14.         length++;  
  15.     }  
  16.   
  17.     int numberArray[100];  
  18.     int index = 0;  
  19.   
  20.     for(int i = 0;i < length;i++)  
  21.     {  
  22.         if(keyChar  == context[i])  
  23.             numberArray[index++] = i;  
  24.     }  
  25.   
  26.     for(int i = 0;i < index;i++)  
  27.     {  
  28.         std::cout<<numberArray[i];  
  29.     }  
  30.   
  31.     std::cout<<std::endl;  
  32. }  
  33.   
  34. NonterminalExpression::NonterminalExpression(AbstractExpression* ae)  
  35. {  
  36.     terminalExpression = ae;  
  37. }  
  38.   
  39. void NonterminalExpression::Interpreter(const Context& context)  
  40. {  
  41.     std::cout<<"The password is: ";  
  42.     terminalExpression->Interpreter(context);  
  43. }  

main.cpp

[cpp] view plain copy
  1. #include "Interpreter.h"  
  2. #include<iostream>  
  3.   
  4. using namespace std;  
  5.   
  6. int main()  
  7. {  
  8.     AbstractExpression* terminal = new TerminalExpression('c');  
  9.     AbstractExpression* nonTerminal = new NonterminalExpression(terminal);  
  10.   
  11.     //First test.  
  12.     string contextFirst = "character of the cars in this chart.";  
  13.     cout<<"Context: "<<contextFirst<<endl;  
  14.     nonTerminal->Interpreter(contextFirst);  
  15.   
  16.     cout<<endl;  
  17.   
  18.     //Second test.  
  19.     terminal = new TerminalExpression('o');  
  20.     nonTerminal = new NonterminalExpression(terminal);  
  21.   
  22.     string contextSecond = "Thanks everyone for your long time supporting.";  
  23.     cout<<"Context: "<<contextSecond<<endl;  
  24.     nonTerminal->Interpreter(contextSecond);  
  25.   
  26.     return 0;  
  27. }  

输出结果:



【注意事项】

嘿嘿,笔者稍微有点偷懒了。使用typedef将string包装为Context。其实真正的Context应该是一个独立类的哦。

在TerminalExpression的构造器中传入的字符就是解码的关键啦。其实正如前文所说,这个设计模式更加注重内部的行为,因此这段代码最重要的应当是TerminalExpression的Interpreter部分。不过也许会有读者问,为何NonterminalExpression的Interpreter部分非常简单,这是因为,非终止符只是作为一种行为的解释,真正的逻辑应当由终止符自己进行的。当然,由于解释器没有统一的形式与逻辑,因此具体的做法还是因程序而异啦。

转自:http://blog.csdn.net/elezeor/article/details/8643758

0 0