[设计模式] 15 解释器模式 Interpreter
在GOF的《设计模式:可复用面向对象软件的基础》一书中对解释器模式是这样说的:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
就如上面说的那个游戏,我输入up walk 5,我必须按照:移动方向+移动方式+移动距离这种格式输入我的指令,而这种格式的指令就是一种文法,只有按照了我定义的这种文法去输入,才能控制屏幕上的小狗去移动。当然了,我输入up walk 5,屏幕上的小狗肯定是听不懂的,它不知道我输入的是什么,这个时候需要怎么办?我需要一个工具去将我输入的内容翻译成小狗能听懂的东西,而这个工具就是定义中提到的解释器,解释器对我输入的指令进行解释,然后将解释得到的指令发送给屏幕上的小狗,小狗听懂了,就进行实际的移动。
我们在开发中经常用到的正则表达式也是这类问题的代表。我们有的时候需要去匹配电话号码、身份证号;我们不用为了每一种匹配都写一个特定的算法,我们可以为每一种匹配定义一种文法,然后去解释这种文法定义的句子就ok了。
抽象表达式角色(AbstractExpression): 声明一个抽象的解释操作,这个接口为所有具体表达式角色都要实现的。
终结符表达式角色(TerminalExpression): 实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例对应不同的终结符,
终结符就是语言中用到的基本元素,一般不能再被分解,如: x -> xa, 这里a是终结符,因为没有别的规则可以把a变成别的符号,不过x可以变成别的符号,所以x是非终结符。
非终结符表达式角色(NonterminalExpression): 文法中的每条规则对应于一个非终结表达式, 非终结表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
环境角色(Context):包含解释器之外的一些全局信息。
AbstractExpression:声明一个抽象的解释操作,这个接口被抽象语法树中所有的节点所共享;
TernimalExpression:一个句子中的每个终结符需要该类的一个实例,它实现与文法中的终结符相关联的解释操作;
NonternimalExpression:
- 对于文法中的每一条规则都需要一个NonternimalExpression类;
- 为文法中的的每个符号都维护一个AbstractExpression类型的实例变量;
- 为文法中的非终结符实现解释操作,在实现时,一般要递归地调用表示文法符号的那些对象的解释操作;
Context:包含解释器之外的一些全局信息;
Client:构建一个需要进行解释操作的文法句子,然后调用解释操作进行解释。
实际进行解释时,按照以下时序进行的:
- Client构建一个句子,它是NonterminalExpression和TerminalExpression的实例的一个抽象语法树,然后初始化上下文并调用解释操作;
- 每一非终结符表达式节点定义相应子表达式的解释操作。而各终结符表达式的解释操作构成了递归的基础;
- 每一节点的解释操作用作用上下文来存储和访问解释器的状态。
例子:
#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) 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。
[设计模式] 15 解释器模式 Interpreter相关推荐
- 设计模式之15 - 解释器模式Interpreter
1. 解释器模式(Interpreter Pattern)的定义 (1)定义 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. ①文法:即语法规则.在解 ...
- 设计模式之解释器模式(Interpreter)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- 行为型设计模式之解释器模式(Interpreter)
结构 意图 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 适用性 当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用 ...
- 设计模式 笔记 解释器模式 Interpreter
//---------------------------15/04/26---------------------------- //Interpreter 解释器模式----类行为型模式 /* 1 ...
- 【白话设计模式二十二】解释器模式(Interpreter)
为什么80%的码农都做不了架构师?>>> #0 系列目录# 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factory) [白话设计模式二] ...
- 北风设计模式课程---解释器模式(Interpreter Pattern)
北风设计模式课程---解释器模式(Interpreter Pattern) 一.总结 一句话总结: 不仅要通过视频学,还要看别的博客里面的介绍,搜讲解,搜作用,搜实例 设计模式都是对生活的抽象,比如用 ...
- python实现解释器_Python设计模式之解释器模式
解释器模式 对每个应用来说,至少有以下两种不同的用户分类. 基本用户:这类用户只希望能够凭直觉使用应用.他们不喜欢花太多时间配置或学习应用的内部.对他们来说,基本的用法就足够了. 高级用户:这些用户, ...
- 设计模式之---解释器模式
解释器模式概述 解释器模式是一种使用频率相对较低但学习难度较大的设计模式,它用于描述如何使用面向对象语言构成一个简单的语言解释器.在某些情况下,为了更好地描述某一些特定类型的问题,我们可以创建一种新的 ...
- java 设计模式之解释器模式(十九)
java 设计模式之解释器模式①⑨ 定义 角色分析 使用场景 代码实现 躁动的心灵,不安的灵魂.在彷徨中挣扎,在迷失中探索.时光飞逝,努力不变. 设计模式学习,近期我会把23种设计模式都写成博客,敬请 ...
- 设计模式之解释器模式、例子分析
1. 定义 解释器模式( interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子 2. 参考 https://blog.csdn.ne ...
最新文章
- leetcode 3. Longest Substring Without Repeating Characters 最长非重复子串的长度 滑动窗口法
- 【设计模式】中介者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
- 多线程并发下的单例模式
- selenium自动化测试、Python单元测试unittest框架以及测试报告和日志输出
- 【译】2019年开始使用Typescript
- 【转】【真正福利】成为专业程序员路上用到的各种优秀资料、神器及框架
- Raki的读paper小记:NATURAL LANGUAGE INFERENCE OVER INTERACTION SPACE
- java jstl 库下载_jar包下载,jstl.jar和standard.jar下载
- 杜比专为旧版本Android,杜比音效7.0清爽卡刷包-杜比音效7.0定制版v2.1.0 安卓版-腾牛安卓网...
- C语言typedef和define、字节对齐的问题
- 推荐术语:CPM、CPC、CPA、CPI、CTR、CPV、CVR
- 魔方cfop公式软件_易烊千玺弟弟7岁破魔方世界纪录,记忆力和毅力惊人
- MAXENT模型的生物多样性生境模拟与保护优先区甄选、自然保护区布局优化及未来气候变化情景下自然保护区优化评估写作技巧
- 计算方法-数值积分与微分
- linux怎么打开chrome_Linux怎么下载应用并安装应用
- vt100 c语言控制,【转】C语言中控制printf的打印颜色实例及vt100的控制符文档
- dns劫持 tplink_路由器dns被劫持有什么后果【图】
- mongodb 3.4.10 更换集群IP
- 垃圾分类从我做起,垃圾分类PPT模板
- Cisco思科命令速查