电子说
解释器模式本质:为某一款软件设计一种脚本语言,序列化软件中的方法,以便通过脚本来操作软件。最典型的例子就是Windows的Powershell,据说作者当年结果很悲催,利用空闲时间开发,还被微软认定为不务正业,做降薪降级处理。
本文目录
一、解释器模式简介
二、解释器模式范例
三、需要安装的软件、工具包
四、共享代码
一、解释器模式简介
解释器模式解决的实际问题:
在软件开发中,会遇到有些问题多次重复出现,而且有一定的相似性和规律性。如果自己设计一个简单的脚本语言,就可以灵活的处理问题,遇到特殊需求可以在软件顶层自定义和扩展功能。使用解释器模式是比较好选着。
解释器模式的定义:
解释器(Interpreter)模式的定义:给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。——维基百科
解释器模式的优点如下:
1、扩展性好。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承扩展功能,符合开闭原则。
2、容易实现。在语法树中的每个表达式节点类都是相似的,所以实现其扩展较为容易。
3、组合复用。可以通过组合复用已有的功能实现新的功能(在性能要求不高的前提下)。
解释器模式的缺点如下:
1、比正常的生成的代码执行效率低。解释器模式中通常使用大量的循环和递归调用,当要解释的句子较复杂时,其调用效率低,适当约束使用范围,不要将其完全当通用编程语言使用,限制递归调用次数,使系统逻辑清晰,更容易调试。
2、会增加很多类。解释器模式中的每条规则至少需要定义一个类,当系统包含的规则越多,类的个数就越多,会导致类级数膨胀,尽量使用当前功能组合,除非特别强调性能才新添语法规则。
解释器模式包含以下主要角色:
1、AbstractExpression(抽象表达式):在抽象表达式中声明了抽象的解释操作,它是所有终结符表达式和非终结符表达式的公共父类。(抽象编程下可以一直递归下去主要包含解释方法 )
2、终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。(不可以递归的点的节点,直接得到结果)
3、非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。(作为一个语法转折点,可以持续递归,和抽象表达式相通)
4、Context(环境类):环境类又称为上下文类,保存中间变量等功能。
解释器的UML关系图如下:
二、解释器模式范例
我们以计算为例来写一个解释器模式,具体UML关系如下图:
1、终结符:Variant T:
1.1、Variant T:Double T、String T;
2、非终结符:Calc T、System T两类。
2.1、Calc T:Add 、Sub;
2.2、System:Show Variable。
计算的文法规则为FUN,V1,V3,V3,......:其中首个字符串FUN为表达式名称,V1,V2,V3....为变量,输入输出为FUN规定,其中用逗号隔开,为了方便使用中英文逗号均可。
例子:SUB,a,b,c含义为a+b=c =>ADD,第一个字符串为表达式名称,a,b类型为变量或常数,c为变量或空字符,为变量时保存数据,为空字符不保存结果,变量不能以数字开头。
下边开始编程。
1、创建三个类AbstractExpression、Noterminal Expression和Terminal Expression,其中Noterminal Expression和Terminal Expression继承至AbstractExpression。当前类关系如下图:
2、创建一个类命名为Context。
3、在AbstractExpression添加两个动态VI Interpert(Info)和Tostring()提供给子类重写。
4、创建类Variant T、Calc T、System T继承至Terminal Expression,当前类关系如下图:
5、创建类Double T、String T继承至Variant T,当前类关系如下图:
6、创建类ADD Sub继承至Calc T,当前类关系如下图:
7、创建类Show Variable继承至System T,当前类关系如下图:
8、为Context添加私有属性和方法。
8.1、添加一个数据引用,值类型为变体,命名为Variable Map;
8.2、添加字符串引用并命名为Log ref,创建其数据成员访问;
8.3、添加静态VI命名为Get Variabe,用于获取数据中的表达式。
8.4、添加静态VI命名为Set Variabe,用于保存数据中的表达式。
8.5、添加一个静态VI命名为Do Interpert,用于执行文本表达式,其工作方式是先获取表达式,然后执行Interpert()动态方法。
8.6、创建Write Log方法,用于打印执行各种状态。
8.7、创建Initial Variable方法,初始化数据引用。
8.8、创建Dispose Variable方法,销毁其数据引用。
先创建终结表达式的成员方法:
9、在Double T中添加数值控件并创建其数据成员访问、重写Double T父类方法Interpert(Info)和Tostring(),先在表达式寻找是否存在,如果存在则为变量,不存在则为常量。
10、在String T中添加字符控件并创建其数据成员访问、重写Double T父类方法Interpert(Info)和Tostring()。
11、在ADD的私有数据中添加三个AbstractExpression命名为x,y,Result并创建其数据成员访问,三个数据分别表示计算输入和输出结果。然后重写Interpert(Info)和Tostring()。
11、在SUB的私有数据中添加三个AbstractExpression命名为x,y,Result并创建其数据成员访问,三个数据分别表示计算输入和输出结果。然后重写Interpert(Info)和Tostring()。
12、重写Show Variable的动态方法,如果是变量就对变量执行Tostring操作然后显示,如果不是就直接显示。
下边使用使用上边的类编写运行代码:
13、创建一个VI命名为Example,放置Context、double T、String T、ADD、SUB、Show Variable。如下图连线,其中a、b、c为double T。
14、创建一个字符串显示控件,创建其引用设置到Context中,在后端添加Do Interpert和文本表达式后,在前后添加创建和销毁引用方法。文本注释:
ADD,100,10,a//a=100+10
Show,ADD//显示ADD的计算过程
Show,a//显示参数a的值
SUB,a,b,c//c=a+b
Show,SUB//显示SUB的计算过程
Show,c//显示参数c的值
15、下边图片是输出结果:
小结:上面的代码完全实现了开始的设想,运行时将文本表达式翻译成代码执行结果,将结果保存到定义的变量中。
上面代码还存在一些问题:
1、当函数输入错误时的处理;
2、参数输入错误的处理,参数的表达式定义;
3、逻辑控制 if for call SubContext。
本文是自动化测试架构的核心内容,本来想放到Pro里讲解,但是觉得没意义,直接在这里写完,Pro里会有部分优秀的设计加进去完善部分功能,这个也是我写文章的核心宗旨:写一些有用的设计,而且可以帮助读者实际工作中应用,不会只讲大道理。
全部0条评论
快来发表一下你的评论吧 !