热门问题
时间线
聊天
视角

解釋器模式

来自维基百科,自由的百科全书

解释器模式
Remove ads

計算機編程中,解釋器模式是一種設計模式[1],它規定了如何求值一個語言中的句子。基本想法是使專用計算機語言的每個符號(終結符與非終結符)都有一個。這個語言中句子的語法樹合成模式的一個實例,它被用來為客戶求值(解釋)這個句子[2]:243

Thumb
解釋器模式的UML類圖

結構

Thumb
解釋器模式的樣例UML類圖和對象圖[3]

在上面的UML類圖中:

  • 客戶Client類提及公共的AbstractExpression接口來解釋一個表達式interpret(context)
  • 終結表達式TerminalExpression類沒有子表達式並且直接解釋一個表達式。
  • 非終結表達式NonTerminalExpression類維護一個子表達式的容器(expressions)並且將解釋請求轉發給這些expressions

對象圖展示了運行時交互:

  • 客戶Client對象發送解釋請求到抽象語法樹。這個請求被沿着樹結構轉發到(辦理於)所有對象。
  • 非終結表達式NonTerminalExpression對象(ntExpr1,ntExpr2)將請求轉發到它們的子表達式。
  • 終結表達式TerminalExpression對象(tExpr1,tExpr2,…)直接的進行解釋。

示例

下面的例子是基於《設計模式》書中先於C++98的樣例代碼的C++11實現。

#include <iostream>
#include <map>
#include <cstring>

class Context;

class BooleanExp {
public:
    BooleanExp() = default;
    virtual ~BooleanExp() = default;
    virtual bool evaluate(Context&) = 0;
    virtual BooleanExp* replace(const char*, BooleanExp&) = 0;
    virtual BooleanExp* copy() const = 0;
};

class VariableExp;

class Context {
public:
    Context() :m() {}
    bool lookup(const VariableExp* key) { return m.at(key); }
    void assign(VariableExp* key, bool value) { m[key] = value; }
private:
    std::map<const VariableExp*, bool> m;
};

class VariableExp : public BooleanExp {
public:
    VariableExp(const char* name_) :name(nullptr) {
        name = strdup(name_);
    }
    virtual ~VariableExp() = default;
    virtual bool evaluate(Context& aContext) {
        return aContext.lookup(this);
    }
    virtual BooleanExp* replace( const char* name_, BooleanExp& exp ) {
        if (0 == strcmp(name_, name)) {
            return exp.copy();
        } else {
            return new VariableExp(name);
        }
    }
    virtual BooleanExp* copy() const {
        return new VariableExp(name);
    }
    VariableExp(const VariableExp&) = delete; // rule of three
    VariableExp& operator=(const VariableExp&) = delete;
private:
    char* name;
};

class AndExp : public BooleanExp {
public:
    AndExp(BooleanExp* op1, BooleanExp* op2)
        :operand1(nullptr), operand2(nullptr) {
        operand1 = op1;
        operand2 = op2;
    }
    virtual ~AndExp() = default;
    virtual bool evaluate(Context& aContext) {
        return operand1->evaluate(aContext) && operand2->evaluate(aContext);
    }
    virtual BooleanExp* replace(const char* name_, BooleanExp& exp) {
        return new AndExp(
            operand1->replace(name_, exp),
            operand2->replace(name_, exp)
        );
    }
    virtual BooleanExp* copy() const {
        return new AndExp(operand1->copy(), operand2->copy());
    }
    AndExp(const AndExp&) = delete; // rule of three
    AndExp& operator=(const AndExp&) = delete;
private:
    BooleanExp* operand1;
    BooleanExp* operand2;
};

int main() {
    BooleanExp* expression;
    Context context;
    VariableExp* x = new VariableExp("X");
    VariableExp* y = new VariableExp("Y");
    expression = new AndExp(x, y);

    context.assign(x, false);
    context.assign(y, true);
    bool result = expression->evaluate(context);
    std::cout << result << '\n';

    context.assign(x, true);
    context.assign(y, true);
    result = expression->evaluate(context);
    std::cout << result << '\n';
}

程序輸出為:

0
1
Remove ads

參見

引用

外部連結

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads