设计模式 笔记 解释器模式 Interpreter
//---------------------------15/04/26----------------------------
//Interpreter 解释器模式----类行为型模式
/*
1:意图:
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
2:动机:
3:适用性:
当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法书时,可使用解释器模式。当
存在以下情况时该模式效果最好:
1>该文法简单对于复杂的文法,文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是
更好的选择。它们无需构建抽象语法树即可解释表达式。这样可以节省空间而且节省时间。
2>效率不是一个关键问题,最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成
另外一种形式。
4:结构:
|-----------Context
|
Client------------------>AbstractExpression:<--------------------
Interpret(Context) |
| |
--------------------- |
| | |
TerminalExpression: NonterminalExpression:---
Interpret(Context) Interpret(Context)
5:参与者:
1>AbstractExpression:
声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
2>TerminalExpression(终结):
1)实现与文法中的终结符相关联的解释操作。
2)一个句子中的每个终结符需要该类的一个实例。
3>NonterminalExpression(非终结):
1)对文法中的每一条规则R::R1R2...Rn都需要一个NonterminalExpression类。
2)为从R1到Rn的每个符号都维护一个AbstractExpression类型的实例变量。
3)为文法中的非终结符实现解释操作。解释一般要递归地调用表示R1到Rn的那些对象的解释操作。
4>Context:
包含解释器之外的一些全局信息。
5>Client:
1)构建表示该文法定义的语言中一个特定的句子的抽象语法树。该抽象语法树由
NonterminalExpression和TerminalExpression的实例装配而成。
2)调用解释操作
6:协作:
1>Client构建一个句子,它是NonterminalExpression和TerminalExpression的实例的一个抽象语法
树,然后初始化上下文并调用解释操作。
2>每一非终结符表达式节点定义相应子表达式的解释操作。而各终结符表达式的解释操作构成了递归的基础。
3>每一节点的解释操作用上下文来存储和访问解释器的状态。
7:效果:
1>优点:
1)易于改变和扩张文法:
因为该模式使用类来表示文法规则,你可食用继承来改变或扩展该文法。已有的表达式可被增量式地
改变,而新的表达式可定义为旧表达式的变体。
2)易于实现文法:
定义抽象语法树中各个节点的类的实现大体类似。这些类易于直接编写,通常它们也可用一个编辑器
或语法分析程序生成器自动生成。
3)增加了新的解释表达式的方式:
解释器模式使得实现新表达式变的容易。
2>缺点:
1)复杂的文法难以维护:
解释器模式为文法中的每一条规则至少定义了一个类,所以包含许多规则的文法可能难以管理和维护。
8:实现:
1>创建抽象语法树:
解释器模式并未解释如何创建一个抽象的语法树。它只提供创建的规则。
2>定义解释操作:
并不一定要在表达式类中定义解释操作。可以配合Visitor模式,创建新的解释器。
3>与Flyweight模式共享终结符:
终结节点一般不存储它们在抽象语法树中位置的信息。在解释过程中,任何它们所需要的上下文信息都由父
节点传递给它们。所以可以配合Flyweight模式。
9:代码示例: */
文法定义:
BooleanExp ::= VariableExp | Constant | OrExp | AndExp | NotExp |'(' BooleanExp
')'
AndExp ::= BooleanExp'and' BooleanExp
OrExp ::= BooleanExp'or' BooleanExp
NotExp ::='not' BooleanExp
Constant ::='true' |
'false'
VariableExp ::='A' |
'B' | ... |'Y' |
'z'
//AbstractExpression:定义了操作
class BooleanExp
{
public:
BooleanExp();
virtual ~BooleanExp();
virtual
;
virtual BooleanExp* Replace(constchar*, BooleanExp&) =
;
virtual BooleanExp* Copy()
;
};
//Contex:定义了变量到布尔值的映射
class Context
{
public:
//检查一个变量返回什么bool值。
bool LookUp(constchar*)
const;
void Assign(VariableExp*,
bool);
};
//TerminalExpression:定义了终止符表达式,也就是说这个类既是表达式,也算单个变量,因为
//它是终止符了
class VariableExp :public BooleanExp
{
public:
VariableExp(constchar*);
virtual ~VariableExp();
virtual
bool Evaluate(Constext&);
virtual BooleanExp* Replace(constchar*, BooleanExp&);
virtual BooleanExp* Copy()
const ;
private:
char* _name;
};
VariableExp::VariableExp(constchar*)
{
_name = strdup(name);
}
//求值,直接借助Context类的LookUp返回布尔值
bool VariableExp::Evaluate(Context& aContext)
{
return aContext.LookUp(_name);
}
BooleanExp* VariableExp::Copy()const
{
return
new VariableExp(_name);
}
//替换,如果变量的name和自己相等,就返回一个拷贝,否则用自己的name来创建一个变量
BooleanExp* VariableExp::Replace(constchar* name, BooleanExp& exp)
{
if(strcmp(name, _name) ==
)
{
return exp.Copy();
}
else
{
return
new VariableExp(_name);
}
}
//NonterminalExpression:and操作,借助AbstractExpression接口接可以实现了
class AndExp :public BooleanExp
{
public:
AndExp(BooleanExp*, BooleanExp*);
virtual ~AndExp();
virtual
bool Evaluate(Constext&);
virtual BooleanExp* Replace(constchar*, BooleanExp&);
virtual BooleanExp* Copy()
const ;
private:
BooleanExp* _operand1;
BooleanExp* _operand2;
};
//要and就把内部的两个表达式and一下
AndExp::AndExp(BooleanExp* op1, BooleanExp* op2): _operand1(op1), _operand2(op2)
{
}
bool AndExp::Evaluate(Context& aContext)
{
return _operand1->Evaluate(aContext) && _operand2->Evaluate(aContext);
}
//要copy就把内部的两个表达式一起copy一下。
BooleanExp* AndExp::Copy()const
{
return AndExp(_operand1->Copy(), _operand2->Copy());
}
//要替换就,一起替换。
BooleanExp* AndExp::Replace(constchar* name, BooleanExp& exp)
{
return
new AndExp(_operand1->Replace(name, exp,)
_operand2->Replace(name,exp));
}
//说明一下,NonterminalExpression类是无需关心底部具体操作的,这些事归TerminalExpression管
//它们只要调用接口就行了。
//使用:
(trueand x)
or (yand (not x))
//也就是 OrExp(AndExp(true, x), AndExp(y, NotExp(x)))
BooleanExp* expression;
Context context;
VariableExp* x =new VariableExp("X");
VariableExp* y =new VariableExp("Y");
expression =new OrExp(
new AndExp(new Constant(true), x),
new AndExp(y,
new NotExp(x)));
context.Assign(x,false);
context.Assign(y,true);
bool result = expression->Evaluate(context);
//Constant类也算一个终止符,不过这个终止符不需要context来确定返回值,它不管constext的情况
//都返回固定的值。但是为了接口统一,它也要接受一个context,看起来像这样:
bool Constant::Evaluate(Context&)
{
return _boolean;
}
设计模式 笔记 解释器模式 Interpreter的更多相关文章
- 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern)
原文:乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) 作 ...
- C#设计模式:解释器模式(Interpreter Pattern)
一,C#设计模式:解释器模式(Interpreter Pattern) 1,解释器模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易 ...
- 二十四种设计模式:解释器模式(Interpreter Pattern)
解释器模式(Interpreter Pattern) 介绍给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子. 示例有一个Message实体类,某个类对它的 ...
- [设计模式] 15 解释器模式 Interpreter
在GOF的<设计模式:可复用面向对象软件的基础>一书中对解释器模式是这样说的:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子.如果一种特定类 ...
- 设计模式之解释器模式(Interpreter)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- 学习笔记——解释器模式Interpreter
解释器模式,其实就是编译原理中的语法解释器,如果用在项目中,可以用于实现动态脚本的解析,也就是说项目可以支持用户脚本扩展. 但实际上,这种运行时解释,效率很慢,如果不是很需要的话,不建议使用. 一种简 ...
- 行为型设计模式之解释器模式(Interpreter)
结构 意图 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 适用性 当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用 ...
- 再起航,我的学习笔记之JavaScript设计模式26(解释器模式)
解释器模式 概念介绍 解释器模式(Interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 获取元素在页面中的路径 我们都知道获取一个 ...
- 解释器模式 Interpreter 行为型 设计模式(十九)
解释器模式(Interpreter) 考虑上图中计算器的例子 设计可以用于计算加减运算(简单起见,省略乘除),你会怎么做? 你可能会定义一个工具类,工具类中有N多静态方法 比如定义了两个 ...
随机推荐
- python类的内置方法
1,__init__(self) 初始化方法,实例化一个对象的时候就会被执行 2,__call__(self,*args) 把实例对象作为函数调用,即实例化一个对象后,在对象后面加括号即可调用__ca ...
- 使用代码段遍历,枚举类型Enum
最近项目中定义了一些枚举类型,需要将枚举的键值传给前端,用于制作下拉菜单. 1.首先定义了枚举类型 public enum 请假类型 : int { 病假 = 1, 事假 = 2, 婚假 = 3, 产 ...
- 从专用磁盘创建 Windows VM
通过使用 Powershell 将专用托管磁盘附加为 OS 磁盘来创建新 VM. 专用磁盘是保留原始 VM 中的用户帐户.应用程序和其他状态数据的现有 VM 中虚拟硬盘 (VHD) 的副本. 使用专用 ...
- 转:前端js、jQuery实现日期格式化、字符串格式化
1. js仿后台的字符串的StringFormat方法 在做前端页面时候,经常会对字符串进行拼接处理,但是直接使用字符串拼接,不但影响阅读,而且影响执行效率,且jQuery有没有定义字符串的Strin ...
- Shallwe学长的模拟赛
NOIP Simulated Test 这个名字一听就很高端. T1:sGCD:http://uoj.ac/problem/48 题意概述:给定一个长度为$n$的序列,求$sgcd(a_1,a_i)$ ...
- 将"a"标签当bunton使用
<a href="javascript:void(0);" style="color: red" onclick="del_product_in ...
- php.ini 常用 配置
参考:http://legolas.blog.51cto.com/2682485/493917这个文件必须命名为''php.ini''并放置在httpd.conf中的PHPIniDir指令指定的目录中 ...
- oneinstack远程管理数据库
本篇文章主要内容是本地工具连接数据非网页(网站)连接 如果你想使用网页(网站)连接远程数据库,请看下面的官网教程 OneinStack如何配置MySQL远程连接? 为了安全考虑,OneinStack仅 ...
- [转]C#操作INI文件
在很多的程序中,我们都会看到有以.ini为后缀名的文件,这个文件可以很方便的对程序配置的一些信息进行设置和读取,比如说我们在做一个程序后台登陆的时候,需要自动登录或者是远程配置数据库连接,及保存密码设 ...
- leetcode367--Valid Perfect Square
Given a positive integer num, write a function which returns True if num is a perfect square else Fa ...