解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。解释器模式要解决的是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
解释器模式结构图
image解释器模式基本代码
#include <iostream>
#include <string>
using namespace std;
class Context { // 包含解释器之外的全局信息
private:
string input;
string output;
public:
void SetInput(string i) { input = i; }
string GetInput() { return input; }
void SetOutput(string o) { output = o; }
string GetOutput() { return output; }
};
class AbstractExpression {
public:
virtual void Interpret(Context* context) = 0;
virtual ~AbstractExpression() {}
};
class TerminalExpression : public AbstractExpression { // 终结符表达式
public:
void Interpret(Context* context) {
cout << "TerminalExpression: " << context->GetInput() << ", " << context->GetOutput() << endl;
}
};
class NonterminalExpression : public AbstractExpression { // 非终结符表达式
private:
AbstractExpression* expression;
public:
NonterminalExpression(AbstractExpression* e) { expression = e; }
void Interpret(Context* context) {
cout << "NonterminalExpression: " << context->GetInput() << ", " << context->GetOutput() << endl;
expression->Interpret(context);
}
};
int main() {
Context* c = new Context();
c->SetInput("Hello");
c->SetOutput("World");
AbstractExpression* exp1 = new TerminalExpression();
AbstractExpression* exp2 = new NonterminalExpression(exp1);
exp1->Interpret(c); // TerminalExpression: Hello, World
exp2->Interpret(c); // NonterminalExpression: Hello, World
// TerminalExpression: Hello, World
delete exp1;
delete exp2;
}
应用场景
当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
优点:
用了解释器模式,就意味着可以容易地改变和扩展文法,因为该模式使用类来表示文法规则,可用继承来改变或者扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。
缺点:
解释器为每一条规则至少定义了一个类,因此包含许多规则的文法可能难以维护和管理。当文法非常复杂时,使用其他技术如语法分析程序或编译器声称器来处理。
网友评论