我所理解的设计模式(C++实现)——解释器模式(Interpreter Pattern)
概述:
未来机器智能化已然成为趋势,现在手机都能听懂英语和普通话,那我大中华几万种方言的被智能化也许也是趋势,我们的方言虽然和普通话相似,但是还是不一样的。这可能需要一个新的语法分析器来帮助我们。
我们的解释器模式就是描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。
但是解释一门自然语言是复杂的过程,我们以加减运算为例子来详细解释解释器模式。
类图和实例:
抽象表达式角色(AbstractExpression): 声明一个抽象的解释操作,这个接口为所有具体表达式角色都要实现的。
终结符表达式角色(TerminalExpression): 实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例对应不同的终结符,
终结符就是语言中用到的基本元素,一般不能再被分解,如: x -> xa, 这里a是终结符,因为没有别的规则可以把a变成别的符号,不过x可以变成别的符号,所以x是非终结符。
非终结符表达式角色(NonterminalExpression): 文法中的每条规则对应于一个非终结表达式, 非终结表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
环境角色(Context):包含解释器之外的一些全局信息。
实例:
#include <iostream>
#include <map>
#include <string> using namespace std; class Context
{
private:
map<string, int> valueMap; public:
void addValue(string key,int value)
{
valueMap.insert(std::pair<string,int>(key,value));
} int getValue(string key)
{
return valueMap[key];
}
}; class AbstractExpression
{
public :
virtual int interpreter(Context context) = 0;
}; class AddNonterminalExpression : public AbstractExpression
{
private :
AbstractExpression *left;
AbstractExpression *right; public:
AddNonterminalExpression(AbstractExpression *left, AbstractExpression *right)
{
this->left = left;
this->right = right;
} int interpreter(Context context)
{
return this->left->interpreter(context) + this->right->interpreter(context);
} }; class SubtractNonterminalExpression : public AbstractExpression
{
private :
AbstractExpression *left;
AbstractExpression *right; public:
SubtractNonterminalExpression(AbstractExpression *left, AbstractExpression *right)
{
this->left = left;
this->right = right;
} int interpreter(Context context)
{
return this->left->interpreter(context) - this->right->interpreter(context);
} }; class TerminalExpression : public AbstractExpression
{
private :
int i; public :
TerminalExpression(int i)
{
this->i = i;
} int interpreter(Context context)
{
return this->i;
}
}; int main(){
//a-b+c
Context context;
context.addValue("a", 7);
context.addValue("b", 8);
context.addValue("c", 2); SubtractNonterminalExpression *subtractValue = new SubtractNonterminalExpression(new TerminalExpression(
context.getValue("a")), new TerminalExpression(context.getValue("b"))); AddNonterminalExpression *addValue = new AddNonterminalExpression(subtractValue, new TerminalExpression(
context.getValue("c"))); cout<< addValue->interpreter(context); return 0;
}
适用性:
在以下情况下可以考虑使用解释器模式:
(1) 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
(2) 一些重复出现的问题可以用一种简单的语言来进行表达。
(3) 一个语言的文法较为简单。
(4) 执行效率不是关键问题。(注:高效的解释器通常不是通过直接解释抽象语法树来实现的,而是需要将它们转换成其他形式,使用解释器模式的执行效率并不高。)
优缺点:
优点:
(1) 易于改变和扩展文法。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
(2) 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
(3) 实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。
(4) 增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合“开闭原则”。
缺点:
(1) 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
(2) 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。
总论:
尽量不要在重要模块中使用解释器模式,因为维护困难。在项目中,可以使用脚本语言来代替解释器模式。
LCL_data原创于CSDN.NET【http://blog.csdn.net/lcl_data/article/details/9259905】
其他设计模式请参考:我所理解的设计模式
我所理解的设计模式(C++实现)——解释器模式(Interpreter Pattern)的更多相关文章
- 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern)
原文:乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) 作 ...
- C#设计模式:解释器模式(Interpreter Pattern)
一,C#设计模式:解释器模式(Interpreter Pattern) 1,解释器模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易 ...
- 二十四种设计模式:解释器模式(Interpreter Pattern)
解释器模式(Interpreter Pattern) 介绍给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子. 示例有一个Message实体类,某个类对它的 ...
- C#设计模式——解释器模式(Interpreter Pattern)
一.概述 在软件开发特别是DSL开发中常常需要使用一些相对较复杂的业务语言,如果业务语言使用频率足够高,且使用普通的编程模式来实现会导致非常复杂的变化,那么就可以考虑使用解释器模式构建一个解释器对复杂 ...
- 《JAVA设计模式》之解释器模式(Interpreter)
在阎宏博士的<JAVA与模式>一书中开头是这样描述解释器(Interpreter)模式的: 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个 ...
- 原始的解释器模式(Interpreter Pattern)
解释器模式的定义(现实项目中非常少遇到,因此直接理论先...) 解释器模式是一种依照规定语法进行解析的方案,在如今项目中使用较少,其定义为:给定一门语言,定义它的方法的一种表示,并定义一个解释器,该解 ...
- 十一个行为模式之解释器模式(Interpreter Pattern)
定义: 定义一个语言的文法,可以使用一个解释器来解释其文法.定义终结符和非终结符的统一接口,并使用抽象对象建立非终结符与其它元素的关联. 结构图: AbstractExpression:抽象表达式类, ...
- php解释器模式( interpreter pattern)
... <?php /* The interpreter pattern specifies how to evaluate language grammar or expressions. W ...
- Java进阶篇设计模式之九----- 解释器模式和迭代器模式
前言 在上一篇中我们学习了行为型模式的责任链模式(Chain of Responsibility Pattern)和命令模式(Command Pattern).本篇则来学习下行为型模式的两个模式, 解 ...
- Java设计模式之九 ----- 解释器模式和迭代器模式
前言 在上一篇中我们学习了行为型模式的责任链模式(Chain of Responsibility Pattern)和命令模式(Command Pattern).本篇则来学习下行为型模式的两个模式, 解 ...
随机推荐
- synchronized锁优化
1.自旋锁和自适应自旋锁 sync在JDK1.6之前之所以被称为重量级锁,是因为对于互斥同步的性能来说,影响最大的就是阻塞的实现.挂起线程与恢复线程的操作都需要转入内核态中完成.从用户态转入内核态是比 ...
- [漏洞复现]CVE-2018-4887 Flash 0day
1.漏洞概述 2018年2月1号,Adobe官方发布安全通报(APSA18-01),声明Adobe Flash 28.0.0.137及其之前的版本,存在高危漏洞(CVE-2018-4878). 攻击者 ...
- 1012 The Best Rank (25)(25 point(s))
problem To evaluate the performance of our first year CS majored students, we consider their grades ...
- uboot的使用
嵌入式软件的层次: bootloader +boot_parameter+kernel+ boot filesystem <uboot的编译> 1)将uboot压缩文件拷贝到 linux系 ...
- 工作中怎么解决bug
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 1,看日志 2,看日志解决不了,断点调试 3,网络搜索.
- CF961E Tufurama 主席树
对原问题进行转化 考虑对每个$i$,询问在$j \in [i + 1, a[i]]$中满足$a[j] \geqslant i$的个数 这样子可以做到不重不漏 个数满足差分的性质,使用主席树来维护即可 ...
- 【SPFA】POJ1860-Currency Exchange
[题目大意] 给出每两种货币之间交换的手续费和汇率,求出从当前货币s开始交换,能否赚. [思路] 反向运用SPFA,判断是否有正环.每次队首元素出队之后,判断一下到源点s的距离是否增大,增大则返回tr ...
- bzoj 3671 贪心
想到了从小到大依次填,但想到可能有重复元素,那是就会有分支,就不知怎样办了,最后才发现它是用随机数来调整排列,所以没有重复元素,唉..... /**************************** ...
- HDU 5698 瞬间移动 数学
瞬间移动 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5698 Description 有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次 ...
- Codeforces Round #228 (Div. 1) B. Fox and Minimal path 构造
B. Fox and Minimal path 题目连接: http://codeforces.com/contest/388/problem/B Description Fox Ciel wants ...