首页 理论教育 解释器模式:大话设计模式第24章苹果汁

解释器模式:大话设计模式第24章苹果汁

时间:2023-11-03 理论教育 版权反馈
【摘要】:第二十四章苹果汁——解释器模式24.1苹果汁时间:1月9日地点:大B房间人物:大B,小A这天,大小和小A一起讨论该怎么样榨苹果汁。

解释器模式:大话设计模式第24章苹果汁

第二十四章 苹果汁——解释器模式

24.1 苹果汁

时间:1月9日  地点:大B房间  人物:大B,小A

这天,大小和小A一起讨论该怎么样榨苹果汁。

大B:“休息天我想做点苹果汁给我女朋友喝,但以前每次做出来的汁都有变色的,有什么方法可以做没有变色的吗?”

小A:“最简单的方法:买一台榨汁机,苹果去皮,切成小块,不要核,然后按照操作说明操作。一般是把果肉放到榨汁机中间部位,通电,然后就自动且快速地出来苹果汁。”

大B:“没想到你会做喔!能说一下具体要怎么做吗?”

小A:“首先要准备好原料。也就是苹果100克,凉开水适量。 下面我来说说制作方法吧。1、将苹果洗净去皮,然后用刮子或匙慢慢刮成泥状,即可喂食。2、将苹果洗净,去皮,切成黄豆大小的碎丁,加入凉开水适量,上笼蒸20-30分钟,待稍凉后即可喂食。 3、刮子或匙一定要洗净消毒。 这样做出来的苹果汁是泥香,易消化,美味可口。”

大B:“嘿嘿!不错嘛!下次我就按你的方法试试。”

24.2 解释器模式

大B:“听你这么说来,榨苹果汁就好像是解释器模式。”

小A:“解释器模式?”

大B:“对,定义语言的语法,并且建立一个解释器来解释该语言中的句子。它属于类的行为模式。这里的语言意思是使用规定格式和语法的代码。如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。而且当文法简单、效率不是关键问题的时候效果最好。这也就是解释器模式应用的环境了。”

24.3 解释器模式的组成

大B:“抽象表达式角色:声明一个抽象的解释操作,这个接口为所有具体表达式角色,抽象语法树中的节点,都要实现的。”

小A:“什么叫做抽象语法树呢?”

大B:“抽象语法树的每一个节点都代表一个语句,而在每个节点上都可以执行解释方法。这个解释方法的执行就代表这个语句被解释。由于每一个语句都代表这个语句被解释。由于每一个语句都代表一个常见的问题的实例,因此每一个节点上的解释操作都代表对一个问题实例的解答。”

小A:“这样啊。”(www.xing528.com)

大B:“解释器模式还包括终结符表达式角色:具体表达式。a、现与文法中的终结符相关联的解释操作b、且句子中的每个终结符需要该类的一个实例与之对应。3、终结符表达式角色:具体表达式。a、法中的每条规则R::=R1R2…Rn都需要一个非终结符表带式角色b、于从R1到Rn的每个符号都维护一个抽象表达式角色的实例变量c、现解释操作,解释一般要递归地调用表示从R1到Rn的那些对象的解释操作4、下文(环境)角色:包含解释器之外的一些全局信息。5、户角色:a、建(或者被给定)表示该文法定义的语言中的一个特定的句子的抽象语法树b、用解释操作。”

24.4 解释器模式的优缺点

大B:“释器模式提供了一个简单的方式来执行语法,而且容易修改或者扩展语法。一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。而且在解释器中不同的规则是由不同的类来实现的,这样使得添加一个新的语法规则变得简单。但是解释器模式对于复杂文法难以维护。可以想象一下,每一个规则要对应一个处理类,而且这些类还要递归调用抽象表达式角色,多如乱麻的类交织在一起是多么恐怖的一件事啊!”

小A:“嘿嘿,是啊。”

24.5 解释器模式适用性

大B:“当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。”

小A:“那在什么情况下该模式效果最好?”

大B:“当存在以下情况时该模式效果最好:1、该文法简单对于复杂的文法,文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式,这样可以节省空间而且还可能节省时间。2、效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下,转换器仍可用解释器模式实现,该模式仍是有用的。”

24.6 解释器模式参与者

小A:“解释器模式都有哪些参与者?”

大B:“1、AbstractExpression(抽象表达式)—声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。2、TerminalExpression(终结符表达式)—实现与文法中的终结符相关联的解释操作。—一个句子中的每个终结符需要该类的一个实例。3、NonterminalExpression(非终结符表达式)—对文法中的每一条规则R::=R1R2...Rn都需要一个NonterminalExpression类。—为从R1到Rn的每个符号都维护一个AbstractExpression类型的实例变量。—为文法中的非终结符实现解释(Interpret)操作。解释(Interpret)一般要递归地调用表示R1到Rn的那些对象的解释操作。4、Context(上下文)—包含解释器之外的一些全局信息。5、Client(客户)—构建(或被给定)表示该文法定义的语言中一个特定的句子的抽象语法树。该抽象语法树由NonterminalExpression和TerminalExpression的实例装配而成。—调用解释操作。”

24.7 解释器模式效果

小A:“解释器模式有什么优点和缺点?”

大B:“解释器模式有下列的优点和不足:1、易于改变和扩展文法因为该模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。已有的表达式可被增量式地改变,而新的表达式可定义为旧表达式的变体。2、也易于实现文法定义抽象语法树中各个节点的类的实现大体类似。这些类易于直接编写,通常它们也可用一个编译器或语法分析程序生成器自动生成。3、复杂的文法难以维护解释器模式为文法中的每一条规则至少定义了一个类(使用BNF定义的文法规则需要更多的类)。因此包含许多规则的文法可能难以管理和维护。可应用其他的设计模式来缓解这一问题。但当文法非常复杂时,其他的技术如语法分析程序或编译器生成器更为合适。4、增加了新的解释表达式的方式解释器模式使得实现新表达式‘计算’变得容易。例如:你可以在表达式类上定义一个新的操作以支持优美打印或表达式的类型检查。如果你经常创建新的解释表达式的方式,那么可以考虑使用Visitor模式以避免修改这些代表文法的类。”

24.8 加减乘除

大B:“来举一个加减乘除的例子吧,实现思路来自于《Java与模式》中的例子。每个角色的功能按照上面提到的规范来实现。”

大B:“解释器模式并没有说明如何创建一个抽象语法树,因此它的实现可以多种多样,在上面我们是直接在Test中提供的,当然还有更好、更专业的实现方式。对于终结符,GOF建议采用享元模式来共享它们的拷贝,因为它们要多次重复出现。但是考虑到享元模式的使用局限性,我建议还是当你的系统中终结符重复的足够多的时候再考虑享元模式。”

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈