本系列所有文章来自李建忠老师的设计模式笔记,系列如下: 设计模式(一)面向对象设计原则 23种设计模式(二)组件协作之模板方法 23种设计模式(三)组件协作之策略模式 23种设计模式(四)组件协作之观察者模式 23种设计模式(五)单一职责之装饰模式 23种设计模式(六)单一职责之桥模式 23种设计模式(七)对象创建之工厂方法 23种设计模式(八)对象创建之抽象工厂 23种设计模式(九)对象创建之原型模式 23种设计模式(十)对象创建之构建器 23种设计模式(十一)对象性能之单件模式 23种设计模式(十二)对象性能之享元模式 23种设计模式(十三)接口隔离之门面模式 23种设计模式(十四)接口隔离之代理模式 23种设计模式(十五)接口隔离之适配器 23种设计模式(十六)接口隔离之中介者 23种设计模式(十七)状态变化之状态模式 23种设计模式(十八)状态变化之备忘录 23种设计模式(十九)数据结构之组合模式 23种设计模式(二十)数据结构之迭代器 23种设计模式(二十一)数据结构之职责链 23种设计模式(二十二)行为变化之命令模式 23种设计模式(二十三)行为变化之访问器 23种设计模式(二十四)领域规则之解析器
文章目录
动机模式定义代码要点总结
在特定领域中,某些变化虽然频繁,但可以抽象为某种规则。这时候,结合特定领域,将问题抽象为语法规则,从而给出在该领域下的一般性解决方案。
动机
在软件构建过程中,如果某一特定领域的问题比较复杂,类似的结构不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。
在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。
模式定义
给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。
代码
#include <iostream>
#include <map>
#include <stack>
using namespace std
;
class Expression {
public:
virtual int interpreter(map
<char, int> var
)=0;
virtual ~Expression(){}
};
class VarExpression: public Expression
{
char key
;
public:
VarExpression(const char& key
)
{
this->key
= key
;
}
int interpreter(map
<char, int> var
) override
{
return var
[key
];
}
};
class SymbolExpression : public Expression
{
protected:
Expression
* left
;
Expression
* right
;
public:
SymbolExpression( Expression
* left
, Expression
* right
):
left(left
),right(right
){
}
};
class AddExpression : public SymbolExpression
{
public:
AddExpression(Expression
* left
, Expression
* right
):
SymbolExpression(left
,right
){
}
int interpreter(map
<char, int> var
) override
{
return left
->interpreter(var
) + right
->interpreter(var
);
}
};
class SubExpression : public SymbolExpression
{
public:
SubExpression(Expression
* left
, Expression
* right
):
SymbolExpression(left
,right
){
}
int interpreter(map
<char, int> var
) override
{
return left
->interpreter(var
) - right
->interpreter(var
);
}
};
Expression
* analyse(string expStr
) {
stack
<Expression
*> expStack
;
Expression
* left
= nullptr;
Expression
* right
= nullptr;
for(int i
=0; i
<expStr
.size(); i
++)
{
switch(expStr
[i
])
{
case '+':
left
= expStack
.top();
right
= new VarExpression(expStr
[++i
]);
expStack
.push(new AddExpression(left
, right
));
break;
case '-':
left
= expStack
.top();
right
= new VarExpression(expStr
[++i
]);
expStack
.push(new SubExpression(left
, right
));
break;
default:
expStack
.push(new VarExpression(expStr
[i
]));
}
}
Expression
* expression
= expStack
.top();
return expression
;
}
void release(Expression
* expression
){
}
int main(int argc
, const char * argv
[]) {
string expStr
= "a+b-c+d-e";
map
<char, int> 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));
var
.insert(make_pair('e',10));
Expression
* expression
= analyse(expStr
);
int result
=expression
->interpreter(var
);
cout
<<result
<<endl
;
release(expression
);
return 0;
}
要点总结
Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足”业务规则频繁变化,且类似的结构不断重复出现,并且容易抽象为语法规则的问题“才适合使用Interpreter模式。
使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地”扩展“文法。
Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具。