设计模式十六:Interpreter(解释器)——类行为型模式

Interpreter(解释器)——类行为型模式

 

1.意图
给定一个语言,定义它的一种文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

 

2.动机
如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
解释器模式描述了如何让为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这个句子。

 

3.适用性
当有一个语言需要解释执行,并且你可以将该语言中的一个句子表示为一个抽象语法树时,可使用解释器模式,而当存在以下情况时该模式的效果最好:
1)该文法简单,对于复杂的文法,文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。他们无需构建抽象语法树就可以解释表达式,这样可以节省空间还可以节省时间。
2)效率不是一个关键问题,最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将他们转换成另一种形式。但即使在这种情况下,转换器仍可用解释器模式实现,该模式仍是可用的。

 

4.结构

参考:http://www.cnblogs.com/jqbird/archive/2011/09/07/2169566.html

 

5.参与者
AbstractExpression抽象表达式
声明一个抽象的解释操作,这个接口为语法树中所有的节点所共享
TerminalExpression终结符表达式
实现与文法中的终结符相关联的解释操作
一个句子中的每个终结符需要该类的一个实例
NonterminalExpression非终结符表达式
对文法中的每一条规则都需要一个类
为每个符号都维护一个AbstractExpression类型的实例变量
为文法中的非终结符实现解释操作,一般解释操作需要递归地调用表示所有对象的解释操作
Context上下文
包含解释器之外的一些全局信息
Client客户
构建(或者被给定)表示该文法定义的语言中一个特定的句子的抽象语法树。该抽象语法树由NonterminalExpression和TerminalExpression的实例装配而成

 

6.协作
1)client构建一个句子,是NonterminalExpression和TerminalExpression的实例的一个抽象语法树,然后初始化上下文并调用解释操作。
2)每一非终结符表达式节点定义相应子表达式的解释操作。而各个终结符表达式的解释操作构成了递归的基础
3)每一个节点的解释操作用上下文来存储和访问解释器的状态。

 

7.效果
1)易于扩展和改变文法
2)易于实现文法
3)复杂的文法难以维护
4)增加了新的解释表达式的方式

 

8.实现
1)创建抽象语法树
解释器模式不涉及到语法分析。抽象语法树可以用一个表驱动的语法分析程序来生成,也可以用手写的语法分析程序来创建,或者直接由client提供。
2)定义解释操作
并不一定要在表达式类中定义解释操作
3)与Flyweight模式共享终结符

 

9.代码实例

参考http://www.cnblogs.com/mayvar/archive/2011/09/08/wanghonghua_201109080339.html

 

罗马字符转换为十进制数字:

Expression抽象类:抽象表达式,声明一个抽象的解释器操作,这个抽象类为抽象语法树中所有的节点所共享。

ThousandExpression:用来核对罗马字符中的 M

HundredExpression:用来核对罗马字符中的C, CD, D or CM

TenExpression:用来核对罗马字附中的X, XL, L and XC

OneExpression:用来核对罗马字附中的I, II, III, IV, V, VI, VI, VII, VIII, IX

 

#include<iostream>
#include<string>
#include<list>
using namespace std;

class context
{
public:
    string input;
    int output;
    context(string in)
    {
        input = in;
        output=0;
    }
    string getInput()
    {
        return input;
    }
    void setInput(string s)
    {
        input = s;
    }
    int getOutput()
    {
        return output;
    }
    void setOutput(int m)
    {
        output = m;
    }
};

class Expression
{
public:
    void Interpret(context *c)
    {
        cout<<"the context is "<<c->getInput()<<endl;
        if(c->getInput().length() == 0)
            return;
        if(c->getInput().find(Nine()) == 0)
        {
            cout<<"we got "<<Nine()<<" "<<Multiplier()<<endl;
            c->setOutput(c->getOutput()+(9*Multiplier()));
            c->setInput(c->getInput().substr(2));
        }
        else if(c->getInput().find(Four()) == 0)
        {
            cout<<"we got "<<Four()<<" "<<Multiplier()<<endl;
            c->setOutput(c->getOutput()+(4*Multiplier()));
            c->setInput(c->getInput().substr(2));
        }
        else if(c->getInput().find(Five()) == 0)
        {
            cout<<"we got "<<Five()<<" "<<Multiplier()<<endl;
            c->setOutput(c->getOutput()+(5*Multiplier()));
            c->setInput(c->getInput().substr(1));
        }
        while(c->getInput().find(One()) == 0)
        {
            cout<<"we got "<<One()<<" "<<Multiplier()<<endl;
            c->setOutput(c->getOutput()+(1*Multiplier()));
            c->setInput(c->getInput().substr(1));
        }
    }
    virtual string One(){return "";};
    virtual string Four(){return "";};
    virtual string Five(){return "";};
    virtual string Nine(){return "";};
    virtual int Multiplier(){return 0;};
    
};

class ThousandExpression:public Expression
{
public:
    string One(){return "M";}
    string Four(){return " ";}
    string Five(){return " ";}
    string Nine(){return " ";}
    int Multiplier(){return 1000;}
};

class HundredExpression:public Expression
{
public:
    string One(){return "C";}
    string Four(){return "CD";}
    string Five(){return "D";}
    string Nine(){return "CM";}
    int Multiplier(){return 100;}
};

class TenExpression:public Expression
{
public:
    string One(){return "X";}
    string Four(){return "XL";}
    string Five(){return "L";}
    string Nine(){return "XC";}
    int Multiplier(){return 10;}
};

class OneExpression:public Expression
{
public:
    string One(){return "I";}
    string Four(){return "IV";}
    string Five(){return "V";}
    string Nine(){return "IX";}
    int Multiplier(){return 1;}
};

int main()
{
    string str = "MCMXXVIII";
    context *con = new context(str);

    list<Expression *> tree ;
    tree.push_back(new ThousandExpression());
    tree.push_back(new HundredExpression());
    tree.push_back(new TenExpression());
    tree.push_back(new OneExpression());

    for(list<Expression *>::iterator ite=tree.begin(); ite!=tree.end();ite++)
    {
        (*ite)->Interpret(con);
    }
    cout<<con->getOutput()<<endl;
    system("pause");
}

 

运行结果:

 

 

10.相关模式
composite模式
抽象语法树是一个符合模式的实例
flyweight模式
说明了如何在抽象语法树中共享终结符
iterator
解释器可用迭代器遍历该结构
visitor
可以用来一个类中维护抽象语法树中的各个节点的行为

 

 

posted @ 2012-05-21 10:53  w0w0  阅读(285)  评论(0)    收藏  举报