//---------------------------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. mysql内存管理

    1 内存管理结构 mysql有自己的内存申请和释放机制 mysql层有mem_root innodb层有mem_heap,mem_pool,buf_pool 它们的结构图如下 2 mem_root m ...

  2. 使用 PowerShell 管理 Azure 磁盘

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

  3. Oracle EBS OPM 查询现有量

    --查询现有量 --created by jenrry DECLARE p_inventory_item_id NUMBER := 231652; --NOT NULL p_organization_ ...

  4. SQL Server中数据库文件的存放方式,文件和文件组 (转载)

    简介 在SQL SERVER中,数据库在硬盘上的存储方式和普通文件在Windows中的存储方式没有什么不同,仅仅是几个文件而已.SQL SERVER通过管理逻辑上的文件组的方式来管理文件.理解文件和文 ...

  5. 获取指定时间的Date对象,IE和Chrome的区别(兼容IE)

    网上的大多教程都是 new Date("2016-08-03 00:00:00"); 其实这是Chrome的写法,在IE中并不起作用,在IE中应为 new Date("2 ...

  6. 《SQL Server 2008从入门到精通》--20180717

    目录 1.触发器 1.1.DDL触发器 1.2.DML触发器 1.3.创建触发器 1.3.1.创建DML触发器 1.3.2.创建DDL触发器 1.3.3.嵌套触发器 1.3.4.递归触发器 1.4.管 ...

  7. 灰度发布:灰度很简单,发布很复杂&灰度发布(灰度法则)的6点认识

    什么是灰度发布,其要点有哪些? 最近跟几个聊的来的同行来了一次说聚就聚的晚餐,聊了一下最近的工作情况如何以及未来规划等等,酒足饭饱后我们聊了一个话题“灰度发布”. 因为笔者所负责的产品还没有达到他们产 ...

  8. UNIX高级环境编程(15)进程和内存分配 < 故宫角楼 >

    故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详.   首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表和二叉树)分配额外内 ...

  9. fedora 开启 apache 并 开启目录浏览模式

    在内网中 暂时需要一台 文件 服务器,所以准备安装一台 http服务器并开启目录访问权限.这次使用 apache 在 fedora 28 机器上: 因为 fedora 28 已经包含 httpd 软件 ...

  10. 网络基础之IP地址和子网掩码

    IP地址 IP是英文Internet Protocol的缩写,意思是"网络之间互连的协议",也就是为计算机网络相互连接进行通信而设计的协议.在因特网中,它是能使连接到网上的所有计算 ...