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

设计之禅——解释器模式(译文)

作者头像
夜勿语
发布2020-09-07 10:58:21
2910
发布2020-09-07 10:58:21
举报
文章被收录于专栏:Java升级之路

前言

解释器模式在平时基本上用不到,因此笔者也不打算花太多精力在这上面,但强迫症使然,所以翻译了GeeksForGeeks上面的一篇文章,本文采取意译及注解方式,原文链接Interpreter Pattern

译文

解释器模式是一种行为型模式,它提供一个解析特定语法规则的解释器。

  • 该模式包含一个表达式接口,该表达式族用来解析一些特定的语法规则。此模式常用于sql解析、符号解析引擎等。
  • 该模式执行于解析表达式上,并且每一个表达式都包含终结符和非终结符。如a + b,a、b即为终结符,+为非终结符;那么解析终结符的解释器即为终结符表达式,解析非终结符的解释器为非终结符表达式。
  • 将解释器模式的结构看作树形的话,其终结符表达式就像是组合中的叶子,而非终结符表达式就像是组件一般。

看例子,这里有一个由“+ - 9 8 7”组成的表达式树:

在这里插入图片描述
在这里插入图片描述

解释器模式的类图:

在这里插入图片描述
在这里插入图片描述

由图我们可以看到解释器模式包含以下几个角色:

  • 抽象表达式:声明一个包含interpreter方法的接口,所有终结符表达式或非终结符表达式需要实现该接口并重写该方法。
  • 终结符表达式:重写interpreter方法解析终结符。
  • 非终结符表达式:重写interpreter解析非终结符,如“+、-、*、/”等。
  • Context上下文:保存全局解释器的信息(原文是用String实现,这里没有全部按照其翻译)。
  • 客户端:组装表达式结构,并执行解释器方法interpreter解析表达式。

下面是代码演示简单的四则运算(因原文使用的是String来表现Context,个人感觉不太直观,体现不出Context的作用,因此引用了另一篇博文的例子——设计模式(行为型)之解释器模式(Interpreter Pattern)),首先是表达式族:

代码语言:javascript
复制
// 抽象表达式
public interface Expression {

    int interpret(Context context);
}

// 终结符表达式
public class Variable implements Expression {

    @Override
    public int interpret(Context context) {
    	// 该表达式呈现的是一个随时可更改值的表达式,因此具体值保存在context中
        return context.getValue(this);
    }

}
// 字面量值使用该表达式存储
public class Constant implements Expression {
	
    private int value;

    public Constant(int value) {
        this.value = value;
    }

    @Override
    public int interpret(Context context) {
        return value;
    }
}

// 非终结符表达式
// 加法解析器
public class AddExpression implements Expression {

    private Expression left, right;

    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
        return left.interpret(context) + right.interpret(context);
    }
}
// 减法解析器
public class SubExpression implements Expression {

    Expression left, right;

    public SubExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
        return left.interpret(context) - right.interpret(context);
    }
}
// 乘法解析器
public class MulExpression implements Expression {

    private Expression left, right;

    public MulExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
        return left.interpret(context) * right.interpret(context);
    }
}
// 除法解析器
public class DevExpression implements Expression {

    private Expression left, right;

    public DevExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
        return left.interpret(context) / right.interpret(context);
    }
}

然后是Context类:

代码语言:javascript
复制
public class Context {
	// 使用Map来存储表达式和值
    private Map<Variable, Integer> map = new HashMap<>();
	
	// 将表达式和值存入map
    public void putValue(Variable x, Integer y) {
        map.put(x, y);
    }

	// 通过表达式对象获取对应的值
    public Integer getValue(Variable x) {
        return map.get(x);
    }

}

客户端测试:

代码语言:javascript
复制
    public static void main(String[] args) {
        // 首先创建变量x, y
        Variable x = new Variable();
        Variable y = new Variable();

        // 获取上下文容器,保存变量值
        Context context = new Context();
        context.putValue(x, 5);
        context.putValue(y, 10);
        // 创建常量
        Expression constant = new Constant(100);

        // 计算(x + y) * 100 / x
        Expression expression = new DevExpression(new MulExpression(new AddExpression(x, y), constant), x);
        int res = expression.interpret(context);
        System.out.println(res);
    }

通过上面的例子我们可以发现解释器模式的优点如下:

  • 每个语法都实现自同一个接口,且独立,因此扩展方便,很容易修改已有规则或是扩展新的规则。
  • 实现一个新的语法规则也很容易,因为所有的表达式都实现自同一个接口或继承自同一个抽象类,因此它们彼此之间都具有共通性。

解释器模式的缺点也很明显:

  • 每一个语法规则就需要新定义一个类,因此对于一个具有复杂语法的语言,那么解释器模式就非常难以维护。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/02/13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 译文
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档