热门问题
时间线
聊天
视角
解釋器模式
来自维基百科,自由的百科全书
Remove ads
在計算機編程中,解釋器模式(英語:interpreter pattern),是一種設計模式[1],它規定了如何求值一個語言中的句子。基本想法是使專門計算機語言的每個符號(終結符與非終結符)都有一個類。這個語言中句子的語法樹是合成模式的一個實例,它被用來為客戶求值(解釋)這個句子[2]:243。

結構

- 客戶
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
下面是Python的例子:
from abc import ABC, abstractmethod
class Context():
def __init__(self):
self.var_dict = {}
def lookup(self, key):
return (self.var_dict[key.name]
if key.name in self.var_dict else None)
def assign(self, key, value):
self.var_dict[key.name] = value
class BooleanExp(ABC):
@abstractmethod
def evaluate(self): pass
@abstractmethod
def replace(self): pass
@abstractmethod
def copy(self): pass
class VariableExp(BooleanExp):
def __init__(self, name):
self.name = name
def __str__(self):
return f"({self.name})"
def evaluate(self, context):
return context.lookup(self)
def replace(self, name, exp):
return (exp.copy() if self.name == name
else type(self)(self.name))
def copy(self):
return type(self)(self.name)
class AndExp(BooleanExp):
def __init__(self, opd1=None, opd2=None):
assert opd2 is not None
self.opd1 = opd1
self.opd2 = opd2
def __str__(self):
return f"({self.opd1} and {self.opd2})"
def evaluate(self, context):
opd1 = self.opd1.evaluate(context)
opd2 = self.opd2.evaluate(context)
return opd1 and opd2
def replace(self, name, exp):
opd1 = self.opd1.replace(name, exp)
opd2 = self.opd2.replace(name, exp)
return type(self)(opd1, opd2)
def copy(self):
opd1 = self.opd1.copy()
opd2 = self.opd2.copy()
return type(self)(opd1, opd2)
def demo():
context = Context()
x = VariableExp("X")
y = VariableExp("Y")
exp = AndExp(x, y)
print(exp)
context.assign(x, False)
context.assign(y, True)
print(exp.evaluate(context))
context.assign(x, True)
context.assign(y, True)
print(exp.evaluate(context))
z = VariableExp("Z")
exp1 = exp.replace("X", z)
print(exp1)
print(exp1.evaluate(context))
context.assign(z, False)
print(exp1.evaluate(context))
其輸出:
>>> demo()
((X) and (Y))
False
True
((Z) and (Y))
None
False
Remove ads
參見
引用
外部連結
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads