以下内容均来自GeekBand极客班C++ 设计模式课程(李建忠老师主讲)
在特定领域中,某些变化虽然频繁,但可以抽象为某种规则。这时候,结合特定领域,将问题抽象为语法规则,从而给出在该领域下的一般性解决方案。
典型模式:
Interpreter
在软件构建过程中,如果某一特定领域的问题比较复杂,类似的结构不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。
在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。
我们需要先构建一个有规律的复杂问题:
构建一个能够识别表达式的智能计算器:
string expStr = "a+b-c+d";
正如这个表达式所述,可以千变万化,但是四则运算规律是不会改变的
整个过程可以用树状结构进行表示,比如,a+b = temp,之后向上传递,其二者的和temp和c做减法,一次类推。
假定现在有一个基类:
//基类:总的表达式
class Expression{
public:
virtual int interpreter(map var) = 0;
virtual ~Expression(){}
};
下面书写一个变量表达式,从图中可以看出,是一个叶子结点:
//变量表达式
class VarExpression : public Expression{
char key;
public:
VarExpression(const char & key){
this->key = key;
}
int interpreter(map var){
return var[key];
}
};
下面书写一个符号表达式,从图中可以看出,该结点为根结点:
//符号表达式
class SymbplExpression : public Expression{
//运算符左右两个参数
protected:
Expression * left;
Expression * right;
public:
SymbplExpression(Expression * _left,Expression * _right):
left(_left),right(_right){
}
};
具体运算规则的实现如下:
//实现加法操作
class AddExpression : public SymbplExpression{
public:
AddExpression(Expression * _left,Expression * _right)
:SymbplExpression(_left,_right){
}
//具体进行执行
int interpreter(map var) override {
//返回左子树和右子树的内容,让后将其相加,并返回结果
return left->interpreter(var) + right->interpreter(var);
}
};
//实现减法操作
class SubExpression : public SymbplExpression{
public:
SubExpression(Expression * _left,Expression * _right)
:SymbplExpression(_left,_right){
}
//具体进行执行
int interpreter(map var) override {
//返回左子树和右子树的内容,让后将其相减,并返回结果
return left->interpreter(var) - right->interpreter(var);
}
};
下面我们要构建一颗树,书写一个analyse函数,
Expression * analyse(string expStr){
stack expStack;
Expression * left = nullptr;
Expression * right = nullptr;
for(int i = 0;i
之后进入主函数:
void main(){
string expStr = "a+b-c+d";//正如这个表达式所述,可以千变万化,但是其中的运算法则是不会发生变化的
map var;
//根据情况,将表达式中的变量赋值为实际的数值
var.insert(make_pair('a',5));
var.insert(make_pair('b',2));
var.insert(make_pair('c',1));
var.insert(make_pair('d',6));
Expression * expression = analyse(expStr);//针对表达式进行解析,获得根结点
int result = expression->interpreter(var);
cout<
interpreter函数不断的递归,对表达式进行具体的运算
Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的结构不断重复出现,并且不容易抽象为语法规则的问题”才适合使用Interpreter模式。
使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便的“扩展”文法。
Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具