设为首页 加入收藏

TOP

解释器模式 Interpreter 行为型 设计模式(十九)(一)
2019-09-01 23:33:08 】 浏览:62
Tags:解释 模式 Interpreter 行为 设计模式 十九
 
解释器模式(Interpreter)
 
image_5c108d54_680
考虑上图中计算器的例子
设计可以用于计算加减运算(简单起见,省略乘除),你会怎么做? 
 
你可能会定义一个工具类,工具类中有N多静态方法
比如定义了两个方法用于计算a+b 和 a+b-c
public static int add(int a,int b){
return a+b;
}

public static int add(int a,int b,int c){
return a+b-c;
}
但是很明显,如果形式有限,那么可以针对对应的形式进行编程
如果形势变化非常多,这就不符合要求,因为加法和减法运算,两个运算符与数值可以有无穷种组合方式
比如 a+b+c+d+e+f、a-b-c+d、a-b+c....等等 
用有限的方法参数列表组合的形式,怎么可能表达出无穷的变化?
 
也可以通过函数式接口,能够提高一定的灵活性
package function;

@FunctionalInterface
public interface Function1<A,B,C,D,E,F,G, R> {
R xxxxx(A a,B b,C c,D d,E e,F f,G g);
}
image_5c108d54_4451
好处是可以动态的自定义方程式,但是你可能需要定义很多函数式接口
而且,有限的函数式接口也不能解决无限种可能的
上面的方式都是以有限去应对无限,必然有行不通的时候
显然,你需要一种翻译识别机器,能够解析由数字以及+ - 符号构成的合法的运算序列
如果把运算符和数字都看作节点的话,能够逐个节点的进行读取解析运算
这就是解释器模式的思维
解释器不限定具体的格式,仅仅限定语法,能够识别遵循这种语法的“语言”书写的句子
不固定你的形式,也就是不存在强制为a+b的情形,但是你必须遵循固定语法,数字+ - 符号组成
Java编译器可以识别遵循java语法的表达式和语句,C语言编译器可以识别遵循C语言语法的表达式和语句。说的就是这个意思
 

意图

给定一个语言,定义他的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
解释器模式其实就是编译原理的思维方式
 
如果某种特定类型的问题发生的频率很高,那么就可以考虑将该问题的各个实例表述为一个简单语言中的句子,通过解释器进行识别。
经典的案例就是正则表达式
我们在实际开发中,经常需要判断邮箱地址、手机号码是否正确,如果没有正则表达式
我们需要编写特定的算法函数进行判断,去实现这些规则,比如一个算法可能用来判断是否是邮箱,比如要求必须有@符号
 
正则表达式是用来解决字符串匹配的问题,他是解释器模式思维的一个运用实例
通过定义正则表达式的语法结构,进而通过表达式定义待匹配字符的集合,然后通过通用的算法来解释执行正则表达式
解释器模式将语法规则抽象出来,设置通用的语法规则,然后使用通用算法执行
使用正则表达式你不在需要自己手动实现算法去实现规则,你只需要按照正则表达式的语法,对你需要匹配的字符集合进行描述即可
有现成的通用算法来帮你实现,而语法相对于算法的实现,自然是简单了很多
再比如浏览器解析HTML,我们知道HTML页面是由固定的元素组成的,有他的语法结构
但是一个HTML页面的标签的个数以及标签内容的组合形式却是千变万化的,但是浏览器可以正确的将他们解析呈现出来
这也是一种解释器的模型
 
在解释器模式中,我们需要 将待解决的问题,提取出规则,抽象为一种“语言”
比如加减法运算,规则为:有数值和+- 符号组成的合法序列
加减法运算就不能有乘除,否则就不符合语法
“1+2+3”就是这种语言的一个句子
 
比如遥控汽车的操作按钮,规则为:由前进、后退、左转、右转四种指令组成
遥控汽车就不能有起飞,否则就是不符合语法的
“前进 左转 后退 前进 后退”就是这种语言的一个句子
 
解释器就是要解析出来语句的含义
既然需要将待解决的问题场景提取出规则,那么 如何描述规则呢?
 

语法规则描述

对于语法规则的定义,也有一套规范用于描述
Backus-Naur符号(就是众所周知的BNF或Backus-Naur Form)是描述语言的形式化的数学方法
叫做范式,此后又有扩展的,叫做EBNF
范式基本规则
::= 表示定义,由什么推导出
尖括号 < > 内为必选项;
方括号 [ ] 内为可选项;
大括号 { } 内为可重复0至无数次的项;
圆括号 ( ) 内的所有项为一组,用来控制表达式的优先级
竖线 | 表示或,左右的其中一个
引号内为字符本身,引号外为语法(比如 'for'表示关键字for )
 
有了规则我们就可以对语法进行描述,这是解释器模式的基础工作
比如加减法运算可以这样定义
expression:=value | plus | minus
plus:=expression ‘+’ expression
minus:=expression ‘-’ expression
value:=integer
值的类型为整型数
有加法规则和减法规则
表达式可以是一个值,也可以是一个plus或者minus
而plus和minus又是由表达式结合运算符构成
 
可以看得出来,有递归嵌套的概念
 

抽象语法树

除了使用文法规则来定义规则,还可以通过抽象语法树的图形方式直观的表示语言的构成
文法规则描述了所有的场景,所有条件匹配的都是符合的,不匹配的都是不符合的
符合语法规则的一个“句子”就是语言规则的一个实例
抽象语法树正是对于这个实例的一个描述
一颗抽象语法树对应着语言规则的一个实例
 
关于抽象语法树百科中这样介绍
在计算机科学中,抽象语法树(abstract syntax tree 或者缩写为 AST),或者语法树(syntax tree)
是源代码的抽象语法结构的树状表现形式,这里特指编程语言的源代码。
树上的每个节点都表示源代码中的一种结构。
之所以说语法是「抽象」的,是因为这里的语法并不会表示出真实语法中出现的每个细节。
 
比如 1+2+3+4-5是一个实例
image_5c108d54_58bf
所以说文法规则用于描述语言规则,抽象语法树描述描述语言的一个实例,也就是一个“句子”

结构

image_5c108d54_6382
抽象表达式角色AbstractExpression
声明一个抽象的解释操作,所有的具体表达式操作都需要实现的抽象接口
接口主要是interpret()方法,叫做解释操作
终结符表达式角色TerminalExpression
这是一个具体角色,实现与文法中的终结符相关联的解释操作,主要就是interpret(
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇设计模式系列 - 组合模式 下一篇PHP设计模式的六大设计原则

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目