//---------------------------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的更多相关文章

  1. 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern)

    原文:乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) 作 ...

  2. C#设计模式:解释器模式(Interpreter Pattern)

    一,C#设计模式:解释器模式(Interpreter Pattern) 1,解释器模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易 ...

  3. 二十四种设计模式:解释器模式(Interpreter Pattern)

    解释器模式(Interpreter Pattern) 介绍给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子. 示例有一个Message实体类,某个类对它的 ...

  4. [设计模式] 15 解释器模式 Interpreter

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对解释器模式是这样说的:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子.如果一种特定类 ...

  5. 设计模式之解释器模式(Interpreter)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  6. 学习笔记——解释器模式Interpreter

    解释器模式,其实就是编译原理中的语法解释器,如果用在项目中,可以用于实现动态脚本的解析,也就是说项目可以支持用户脚本扩展. 但实际上,这种运行时解释,效率很慢,如果不是很需要的话,不建议使用. 一种简 ...

  7. 行为型设计模式之解释器模式(Interpreter)

    结构 意图 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 适用性 当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用 ...

  8. 再起航,我的学习笔记之JavaScript设计模式26(解释器模式)

    解释器模式 概念介绍 解释器模式(Interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 获取元素在页面中的路径 我们都知道获取一个 ...

  9. 解释器模式 Interpreter 行为型 设计模式(十九)

      解释器模式(Interpreter)   考虑上图中计算器的例子 设计可以用于计算加减运算(简单起见,省略乘除),你会怎么做?    你可能会定义一个工具类,工具类中有N多静态方法 比如定义了两个 ...

随机推荐

  1. 使用 PowerShell 管理 Azure 磁盘

    Azure 虚拟机使用磁盘来存储 VM 操作系统.应用程序和数据. 创建 VM 时,请务必选择适用于所需工作负荷的磁盘大小和配置. 本教程介绍如何部署和管理 VM 磁盘. 学习内容: OS 磁盘和临时 ...

  2. Linux 下解压 rar 文件

    网上下载rar 压缩文件的使用,在linux在我们需要对其进行解压缩,这个时候,我们需要安装 rar相关的文件,来进行解压缩. 1. 下载 我们进入rarlab网站,进行下载 rar for linu ...

  3. springmvc 笔记一

    Springmvc 处理流程 所需的包 前端配置器 在web.xml中配置 <!-- 配置前端控制器 --> <servlet> <servlet-name>spr ...

  4. python解析式

    一.列表解析式 列表解析是外面一对中括号,它返回的是列表. 一般形式为:[expr for item in itratoble] print([i+1 for i in range(10)]) #结果 ...

  5. Python接口自动化--post提交的四种数据类型 4

    常见的post请求提交的数据类型有四种: 1.第一种:application/json:这是最常见的json格式,如下 {"input1":"XXX",&quo ...

  6. JS控制div跳转到指定的位置的几种解决方案总结

    原文:http://www.jb51.net/article/96574.htm 这篇文章主要介绍了JS控制div跳转到指定的位置的几种解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考 ...

  7. pstools工具使用

    该工具的目的:批量远程操作windows服务器, 个人实验的方法步骤: 1.在被远程的电脑上开通139,445端口 2.建立ipc$链接, 格式:Net use \\目标ip\ipc$ 密码 /use ...

  8. 【转】网络安全——一图看懂HTTPS建立过程

    阅读目录 准备工作(对应图中prepare1234) 发起链接 最后 关于网络安全加密的介绍可以看之前文章: 1. 网络安全——数据的加密与签名,RSA介绍2. Base64编码.MD5.SHA1-S ...

  9. C#中XmlSerializer实现序列化浅析

    C# XmlSerializer类是实现序列化的一个类,那么关于C# XmlSerializer的学习我们要掌握怎么样的操作方法呢?那么这里向你详细介绍具体的操作细节情况. C# XmlSeriali ...

  10. python不要使用可变对象作为参数的默认值

    幽灵乘客例子: . 如上:如果为空时,bus2和bus3引用的是相同的一个list,就会造成粗错误 实际工作中,如果不想改变某个参数值,那么通过以上这种赋值也会改变 解决方式self.passenge ...