【设计模式】之二十三种设计模式--解释器模式

解释器模式

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
(给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。)

通用类图

抽象解释器
定义一个抽象类
终结符表达式类
继承抽象解释器类,通常和抽象解释器一对一,实现与文法中的元素相关联的解释操作
非终结符表达式类
继承抽象解释器类,通常和抽象解释器一对多,文法中的每条规则对应于一个非终结表达式

通用源码

//抽象表达式
template <typename T, typename H>
class Expression {
     
public:
    //每个表达式必须有一个解析任务
    virtual T interpreter(H&) = 0;
};
//终结符表达式
template <typename T, typename H>
class TerminalExpression : public Expression<T, H> {
     
public:
    //通常终结符表达式只有一个,但是有多个对象
    T interpreter(H& h) {
     
        return null;
    }
};
//非终结符表达式
template <typename T, typename H>
class NonerminalExpression : public Expression<T, H> {
     
    //每个非终结符表达式都会对其他表达式产生依赖
    public NonerminalExpression (Expression* e) {
     
    }
    T interpreter(H& h) {
     
        //进行文法处理
        return null;
    }
};

优点

解释器是一个简单语法分析工具,扩展性非常好

缺点

导致类膨胀
采用递归调用方法
效率不高

使用场景

重复发生的问题的场景
一个简单语法需要解释的场景

最佳实践

解释器模式因为性能、效率以及维护问题,一般在实际的系统开发中使用得较少。
如果实在需要用到解释器模式时,可以考虑Expression4J、MESP(Math Expression String Parser)、Jep等开源的解析工具包。

示例代码

#include 
#include 
#include 
#include 

using namespace std;

class Expression {
     
public:
    virtual int interpreter(map<char, int>&) = 0;
};

class VarExpression : public Expression {
     
public:
    VarExpression(char s): key(s) {
      }
    int interpreter(map<char, int>& mci) override {
     
        return mci[key];
    }
private:
    char key;
};

class SymbolExpression : public Expression {
     
public:
    SymbolExpression(Expression* l, Expression* r): left(l), right(r) {
      }
protected:
    Expression* left;
    Expression* right;
};

class AddExpression : public SymbolExpression {
     
public:
    AddExpression(Expression* l, Expression* r): SymbolExpression(l ,r) {
      }
    int interpreter(map<char, int>& mci) override {
     
        return left->interpreter(mci) + right->interpreter(mci);
    }
};

class SubExpression : public SymbolExpression {
     
public:
    SubExpression(Expression* l, Expression* r): SymbolExpression(l ,r) {
      }
    int interpreter(map<char, int>& mci) override {
     
        return left->interpreter(mci) - right->interpreter(mci);
    }
};

class Calculator {
     
public:
    Calculator(string s) {
     
        stack<Expression*> se;
        Expression* left = nullptr;
        Expression* right = nullptr;
        for(int i = 0; i < s.size(); ++i) {
     
            if(s[i] == '+') {
     
                left = se.top();se.pop();
                right = new VarExpression(s[++i]);
                se.push(new AddExpression(left, right));
            }else if(s[i] == '-') {
     
                left = se.top();se.pop();
                right = new VarExpression(s[++i]);
                se.push(new SubExpression(left, right));
            }else {
     
                se.push(new VarExpression(s[i]));
            }
        }
        expression = se.top();se.pop();
    }
    int run(map<char, int> mci) {
     
        return expression->interpreter(mci);
    }
private:
    Expression* expression;
};

int main() {
     
    string s;
    cout << "input Expression: " << endl;
    cin >> s;
    map<char, int> mci;
    for(int i = 0; i < s.size(); ++i) {
     
        if(s[i] != '+' && s[i] != '-') {
     
            cout << "input " << s[i] << " :"<< endl;
            int tmp;
            cin >> tmp;
            mci.insert(make_pair(s[i], tmp));
        }
    }
    Calculator* cal = new Calculator(s);
    cout <<"the answer is: " << cal->run(mci) << endl;
    return 0;
}

你可能感兴趣的:(设计模式)