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

    解释器,似乎应用场景比较固定:解析某种文法(比如正则表达式,编程语言)。

    实际中应用可能不会很多,先拿来了解一下。肯定是理解还不够深入。所没能真正体会其奥妙。

    该模式由上下文、表达式和客户组成。表达式又分为终结节点和非终结节点组成。这种结构天然的会想到用递归。所以性能肯定不是很理想。当然在设计模式那边书里也说了该模式应用场景就是对性能没有严苛的要求的场景。

    终结节点,负责解析该节点处的行为,而非终结节点一般又底层N个终结节点或者非终结节点组成,其工作就是来解释这N个子孙之间在该节点处的行为。

    还是拿老掉牙的计算器来简单写个demo吧:

    /***************************************************************************
     * 
     * Copyright (c) 2013 , Inc. All Rights Reserved
     * 
     **************************************************************************/
      
    /**
     * @file test_interpreter.cpp
     * @author itegel
     * @date 2013/05/30 14:09:57
     * @brief 
     *  
     **/
    
    #include <stdlib.h>
    #include <iostream>
    #include <map>
    #include <string>
    #include <stack>
    using namespace std;
    
    //father
    class Expression{
        public:
            Expression(){}
            ~Expression(){}
            virtual int Interprete() = 0;
            virtual void AboutMe() = 0;
        protected:
            char _key;
            int _val;
    };
    
    //terminal Expression
    class VarExpression : public Expression{
        public:
            VarExpression(char key){
                _key = key;
            }
            virtual int Interprete(){
                return _key-'0';
            }
            virtual void AboutMe(){
                cout<<"(var:"<<_key<<")";
            }
    };
    
    //Nonterminal Expression
    class SymbolExpression : public Expression{
        public:
            SymbolExpression(Expression *left, Expression *right){
                _left = left;
                _right = right;
            }
        virtual int Interprete() = 0;
        virtual void AboutMe() = 0;
       
        protected:
            Expression * _left;
            Expression * _right;
    };
    
    //+
    class AddExpression : public SymbolExpression{
        public:
            AddExpression(Expression *left, Expression *right):SymbolExpression(left,right){}
            virtual int Interprete(){
                return _left->Interprete() + _right->Interprete();
            }
           
            virtual void AboutMe(){
                _left->AboutMe();
                cout<<"(Sym:+)";
                _right->AboutMe();
            }
    };
    
    //-
    class SubExpression : public SymbolExpression{
        public:
            SubExpression(Expression *left, Expression *right):SymbolExpression(left,right){}
            virtual int Interprete(){
                return _left->Interprete() - _right->Interprete();
            }
            
            virtual void AboutMe(){
                _left->AboutMe();
                cout<<"(Sym:-)";
                _right->AboutMe();
            }
    };
    
    //calculator 只支持0-9数字间加减法
    class Calculator{
        public:
            Calculator(const char * expr){
                _expr_str = expr;
                _expression = NULL;
            }
            ~Calculator(){
                if (_expression){
                    delete _expression;
                }
            } 
            void BuildExpression(){
                Expression * left = NULL;
                Expression * right = NULL;
                const char * expr_char = _expr_str;
    
                cout<<"Building Expression"<<endl;
                for (int i = 0; i < strlen(expr_char); i++){
                    switch (expr_char[i]){
                        case '+':
                            cout<<'+';
                            left = tmp_stack.top();
                            right = new VarExpression(expr_char[++i]);
                            cout<<expr_char[i];
                            tmp_stack.push(new AddExpression(left, right));
                            break;
                        case '-':
                            cout<<'-';
                            left = tmp_stack.top();
                            right = new VarExpression(expr_char[++i]);
                            cout<<expr_char[i];
                            tmp_stack.push(new SubExpression(left, right));
                            break;
                        default:
                            cout<<expr_char[i];
                            tmp_stack.push(new VarExpression(expr_char[i]));
                            break;
                    }
                }
                _expression = tmp_stack.top();
            }
    
            Expression * GetExpression(){
                return _expression;
            }
    
        private:
            const char * _expr_str;
            Expression  * _expression;
            stack<Expression *> tmp_stack;
    };
    
    int main(){
    
        Calculator * cal = new Calculator("1+2-3+4-1-2");
        cal->BuildExpression();
        Expression * expr = cal->GetExpression();
        cout<<endl<<endl<<"Builded Expression:"<<endl;
        expr->AboutMe();
        cout<<endl;
        int val = expr->Interprete();
        cout<<endl<<"Expression Val:"<<val<<endl;
    
        return 0;
    }
    

    运行结果:

    Building Expression
    1+2-3+4-1-2

    Builded Expression:
    (var:1)(Sym:+)(var:2)(Sym:-)(var:3)(Sym:+)(var:4)(Sym:-)(var:1)(Sym:-)(var:2)

    Expression Val:1

    从demo看,其实表达式的类结构比较简单,而且每个子类只需要关注自己的行为就好,后续扩展最多也只是扩展出不同的子类,完成对应的操作即可。

    实际上估计最复杂的部分应该是创建表达式树的过程。本例中为了简单只是支持了加减法,而且用char作为操作数,所以只能支持一位数字。

    解释器模式,优点是,扩展新的操作很容易。缺点,都说是性能不好,实际上我也说不出来。

    个人认为其最大的问题是应用场景可能没那么多。

  • 相关阅读:
    preliminary->advanced exam selections
    Maven入门
    Ajax和Json
    过滤器和监听器
    JSTL标签库
    JSP与EL表达式
    dom4j与XML文档操作
    会话管理
    登录之验证码
    WEB之文件下载
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3108998.html
Copyright © 2011-2022 走看看