概念与特点
概念:
解释器模式指的是给分析对象定义一个语言,并定义该语言的文法表示。再设计一个解释器来解释该语句中的句子。用编译语言的方式来分析应用中的实例。
特点:
- 扩展性好。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
- 容易实现。在语法树中的每个表达式节点类都是相似的,所以实现其文法较为容易。
- 执行效率较低。解释器模式中通常使用大量的循环和递归调用,当要解释的句子较复杂时,其运行速度很慢,且代码的调试过程也比较麻烦。
- 会引起类膨胀。解释器模式中的每条规则至少需要定义一个类,当包含的文法规则很多时,类的个数将急剧增加,导致系统难以管理与维护。
结构与实现
结构:
解释器模式包含【抽象表达式】、【终结符表达式】、【非终结符表达式】、【环境】和【客户端】。
【抽象表达式】:定义解释器的接口,约定解释器的解释操作。
【终结符表达式】:抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中每一个终结符都有一个具体终结符表达式与之对应。
【非终结符表达式】:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中每一个非终结符都对应具体终结符表达式。
【环境】:通常包含各个解释器需要的数据或是公共功能。一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
【客户端】:将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,也可以通过环境角色间接访问解释器的解释方法。
案例:
功能描述:假如“韶粵通”公交车读卡器可以判断乘客的身份,如果是“韶关”或者“广州”的“老人” “妇女”“儿童”就可以免费乘车,其他人员乘车一次扣 2 元。
请实现以上功能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
//抽象表达式类
class Expression{
interpret(info){
}
}
//终结符表达式
class TerminalExpression extends Expression{
constructor(data){
super(data);
this.set = new Set(data);
}
interpret(info){
if(this.set.has(info)){
return true
}else {
return false
}
}
}
//非终结符表达式
class AndExpression extends Expression{
constructor(city,person){
super();
this.city = city;
this.person = person;
}
interpret(info){
let s = info.split('的');
return this.city.interpret(s[0])&&this.person.interpret(s[1])
}
}
//环境
class Context {
constructor() {
//定义终结表达式实例和非终结表达式实例
let citys = ["韶关", "广州"];
let persons = ["老人", "妇女", "儿童"];
this.city = new TerminalExpression(citys);
this.person = new TerminalExpression(persons);
this.cityPerson = new AndExpression(this.city, this.person);
}
//根据非终结表达式实例的解释方法做出反应
action(info) {
let ok = this.cityPerson.interpret(info);
if (ok) {
console.log("您是" + info + ",您本次乘车免费!")
} else {
console.log(info + ",您不是免费人员,本次乘车扣费2元!")
}
}
}
class Customer{
static main(){
let bus = new Context();
bus.action("韶关的老人");
bus.action("韶关的年轻人");
bus.action("广州的妇女");
bus.action("广州的儿童");
bus.action("山东的儿童");
}
}
Customer.main();
</script>
</body>
</html>
应用场景
- 当语言的文法较为简单,且执行效率不是关键问题时。
- 当问题重复出现,且可以用一种简单的语言来进行表达时。
- 当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候,如 XML 文档解释。
应用实例
参考以上案例。
总结
解释器模式适用于我们所熟悉的抽象语法树以及一些类似 JSX 语法。
【终结符表达式】:
1、接收并储存匹配对象,
2、提供 interpret 方法,该方法内判断对象是否在匹配对象中。
【非终结符表达式】:
1、接收并储存传入对象,
2、提供 interpret 方法,该方法内通过截取传入对象,调用【终结符表达式】的 interpret 方法判断对象是否在匹配对象中。
【环境】:
1、提供传入对象,
2、实例化并存储【终结符表达式】和【非终结符表达式】,
3、提供 action 方法。该方法内调用【非终结符表达式】的 interpret 方法判断对象是否在匹配对象中从而作出反应。