前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >解释器模式

解释器模式

作者头像
WindrunnerMax
发布2020-11-24 11:21:08
6870
发布2020-11-24 11:21:08
举报
文章被收录于专栏:Czy‘s BlogCzy‘s Blog

解释器模式

解释器模式Interpreter Pattern提供了评估语言的语法或表达式的方式,它属于行为型模式,这种模式实现了一个表达式接口,该接口解释一个特定的上下文,解释器模式通常被用在SQL解析、符号处理引擎等。

描述

在软件开发中,会遇到有些问题多次重复出现,而且有一定的相似性和规律性,如果将它们归纳成一种简单的语言,那么这些问题实例将是该语言的一些句子,这样就可以用编译原理中的解释器模式来实现了。解释器模式是给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子,也就是说,用编译语言的方式来分析应用中的实例。这里提到的文法和句子的概念同编译原理中的描述相同,文法指语言的语法规则,而句子是语言集中的元素。

模式角色

  • 抽象表达式Expression角色: 声明一个所有的具体表达式角色都需要实现的抽象接口,这个接口主要是一个interpret()方法,称做解释操作。
  • 终结符表达式Terminal Expression角色: 实现了抽象表达式角色所要求的接口,主要是一个interpret()方法,文法中的每一个终结符都有一个具体终结表达式与之相对应,比如有一个简单的公式R=R1+R2,在里面R1R2就是终结符,对应的解析R1R2的解释器就是终结符表达式。
  • 非终结符表达式Nonterminal Expression角色: 文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式。
  • 环境Context角色: 这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200,这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。

优点

  • 扩展性好,由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
  • 容易实现,在语法树中的每个表达式节点类都是相似的,所以实现其文法较为容易。

缺点

  • 执行效率较低,解释器模式中通常使用大量的循环和递归调用,当要解释的句子较复杂时,其运行速度很慢,且代码的调试过程也比较麻烦。
  • 会引起类膨胀,解释器模式中的每条规则至少需要定义一个类,当包含的文法规则很多时,类的个数将急剧增加,导致系统难以管理与维护。
  • 可应用的场景比较少,在软件开发中,需要定义语言文法的应用实例非常少,所以这种模式很少被使用到。

实现

代码语言:javascript
复制
function Context() {
    var sum = 0;
    var list = [];
    this.getSum = function() {
        return sum;
    }
    this.setSum = function(_sum) {
        sum = _sum;
    }
    this.add = function(eps) {
        list.push(eps);
    }
    this.getList = function() {
        return list;
    }
}

function PlusExpression() {
    this.interpret = function(context) {
        var sum = context.getSum();
        sum++;
        context.setSum(sum);
    }
}

function MinusExpression() {
    this.interpret = function(context) {
        var sum = context.getSum();
        sum--;
        context.setSum(sum);
    }
}

(function() {
    var context = new Context();
    context.setSum(20);
    //运行加法三次
    context.add(new PlusExpression());
    context.add(new PlusExpression());
    context.add(new PlusExpression());
    //运行减法两次
    context.add(new MinusExpression());
    context.add(new MinusExpression());
    var list = context.getList();
    for (var i = 0; i < list.length; i++) {
        let expression = list[i];
        expression.interpret(context);
    }
    console.log(context.getSum()); // 21
})();

每日一题

代码语言:javascript
复制
https://github.com/WindrunnerMax/EveryDay

参考

代码语言:javascript
复制
http://c.biancheng.net/view/1402.html
https://blog.csdn.net/itpinpai/article/details/51657199
https://www.runoob.com/design-pattern/interpreter-pattern.html
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 解释器模式
    • 描述
      • 模式角色
      • 优点
      • 缺点
    • 实现
      • 每日一题
        • 参考
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档