zoukankan      html  css  js  c++  java
  • 【设计模式】——解释器模式

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

      解释器模式需要解决的问题,如果一个特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

    #include <iostream>
    #include <list>
    using namespace std;
    class Context;
    //AbstractExpression(抽象表达式),声明一个抽象的解释操作,这个接口为抽象语法树中所有的结点所共享
    class AbstractExpression
    {
    public:
        virtual void Interpret(Context *context)=0;
    };
    //TerminalExpression(终结符表达式),实现与文法中的终结符相关联的解释操作。实现抽象表达式中所要求的接口,
    //主要是一个interpret()方法。文法中每一个终结符都有一个具体终结表达式与之相对应。
    class TerminalExpression:public AbstractExpression
    {
    public:
        void Interpret(Context *context)
        {
            cout << "终端解释器" << endl;
        }
    };
    //NonterminalExpression(非终结符表达式),为文法中的非终结符实现解释操作。对文法中每一条规则R1、R2......Rn
    //都需要一个具体的非终结符表达式类。通过实现抽象表达式的interpret()方法实现解释操作。解释操作以递归方式调用
    //上面所提到的代表R1、R2......Rn中各个符号的实例变量
    class NonterminalExpression:public AbstractExpression
    {
    public:
        void Interpret(Context *context)
        {
            cout << "非终端解释器" << endl;
        }
    };
    //Context,包含解释器之外的一些全局信息
    class Context
    {
    private:
        string m_input;
        string m_output;
    public:
        void SetInput(string input)
        {
            this->m_input=input;
        }
        string GetInput()
        {
            return m_input;
        }
        void SetOutput(string output)
        {
            this->m_output=output;
        }
        string GetOutput()
        {
            return m_output;
        }
    };
    //客户端代码,构建表示该文法定义的语言中一个特定的句子的抽象语法树。调用解释操作
    int main()
    {
        Context *context=new Context();
        list<AbstractExpression*> alist;
        alist.push_back(new TerminalExpression());
        alist.push_back(new NonterminalExpression());
        alist.push_back(new TerminalExpression());
        alist.push_back(new TerminalExpression());
        list<AbstractExpression*>::iterator iter=alist.begin();
        for(;iter!=alist.end();iter++)
            (*iter)->Interpret(context);
        return 0;
    }

      当有一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。用了解释器模式,就意味着可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,你可以使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。解释器模式也有不足,解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。

    音乐解释器

    #include <iostream>
    #include <list>
    #include <string>
    #include <string.h>
    #include <cstdlib>
    using namespace std;
    //演奏内容类
    class PlayContext
    {
    private:
        string m_text;
    public:
        void SetText(string text)
        {
            this->m_text=text;
        }
        string GetText()
        {
            return m_text;
        }
    };
    //表达式类
    class Expression
    {
    public:
        void Interpret(PlayContext *context)
        {
            if(context->GetText().length()==0)
                return;
            else
            {
                string playKey=context->GetText().substr(0,1);
                context->SetText(context->GetText().substr(2));
                int nPos=context->GetText().find(" ");
                string strPlayValue=context->GetText().substr(0,nPos);
                int nPlayValue=atoi(strPlayValue.c_str());
                nPos=context->GetText().find(" ");
                context->SetText(context->GetText().substr(nPos+1));
                Execute(playKey,nPlayValue);
            }
        }
        virtual void Execute(string strKey,const int nValue)=0;
    };
    //音符类
    class Note:public Expression
    {
    public:
        void Execute(string strKey,const int nValue)
        {
            char szKey[2];
            strncpy(szKey,strKey.c_str(),strKey.length());
            string note="";
            switch(szKey[0])
            {
            case 'C':
                note="1";
                break;
            case 'D':
                note="2";
                break;
            case 'E':
                note="3";
                break;
            case 'F':
                note="4";
                break;
            case 'G':
                note="5";
                break;
            case 'A':
                note="6";
                break;
            case 'B':
                note="7";
                break;
            }
            cout << note << " ";
        }
    };
    //音阶类
    class Scale:public Expression
    {
    public:
        void Execute(string key,const int value)
        {
            string strScale;
            switch(value)
            {
            case 1:
                strScale="低音";
                break;
            case 2:
                strScale="中音";
                break;
            case 3:
                strScale="高音";
                break;
            }
            cout << strScale << " ";
        }
    };
    //音速类
    class Speed:public Expression
    {
    public:
        void Execute(string key,const int value)
        {
            string speed;
            if(value<500)
                speed="快速";
            else if(value>=1000)
                speed="慢速";
            else
                speed="中速";
            cout << speed << " ";
        }
    };
    int main()
    {
        PlayContext *context=new PlayContext();
        cout << "上海滩:";
        context->SetText("T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 ");
        Expression *expression=NULL;
        while(!context->GetText().empty())
        {
            string str=context->GetText().substr(0,1);
            char szKey[2];
            strncpy(szKey,str.c_str(),str.length());
            switch(szKey[0])
            {
            case 'T':
                expression=new Speed();
                break;
            case 'O':
                expression=new Scale();
                break;
            case 'C':
            case 'D':
            case 'E':
            case 'F':
            case 'G':
            case 'A':
            case 'B':
                expression = new Note();
                break;
            default:
                break;
            }
            if(NULL!=expression)
                expression->Interpret(context);
        }
        return 0;
    }
  • 相关阅读:
    Oracle 的字符集与乱码
    linux 时间同步的2种方法
    2 创建型模式-----工厂方法模式
    条款4:确定对象在使用前已被初始化
    条款3:尽可能地使用const
    条款2:尽量以const、enum、inline替换#define
    条款13:以对象管理资源
    条款12:牢记复制对象的所有成员
    条款11:在operator=中处理“自我赋值”
    条款10:令operator=返回一个*this的引用
  • 原文地址:https://www.cnblogs.com/awy-blog/p/3844408.html
Copyright © 2011-2022 走看看