23种设计模式之解释器模式(Interpreter)

文章目录

概述

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

解释器模式的优缺点

  • 优点
  • 能够很容易地改变和扩展文法,因为该模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。
  • 比较容易实现文法,因为定义抽象语法树中各个节点地类的实现大体类似,这些类都易于直接编写。
  • 缺点
  • 解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。
  • 易引起类膨胀。
  • 可利用的场景较少。
  • 解释器模式采用递归调用方法。

解释器模式的结构和实现

模式结构

  • AbstrExpression: 抽象表达式
  • TerminalExpression: 终结符表达式
  • NonterminalExpression: 非终结符表达式
  • Context: 环境类:包含解释器之外的一些全局信息

模式实现

23种设计模式之解释器模式(Interpreter)

我们将创建一个接口 Expression 和实现了 Expression 接口的实体类。定义作为上下文中主要解释器的 TerminalExpression 类。其他的类 OrExpressionAndExpression 用于创建组合式表达式。

InterpreterPatternDemo,我们的演示类使用 Expression 类创建规则和演示表达式的解析。

Expression.java

public interface Expression {
   public boolean interpret(String context);
}

TerminalExpression.java

public class TerminalExpression implements Expression {

   private String data;

   public TerminalExpression(String data){
      this.data = data;
   }

   @Override
   public boolean interpret(String context) {
      if(context.contains(data)){
         return true;
      }
      return false;
   }
}

OrExpression.java

public class OrExpression implements Expression {

   private Expression expr1 = null;
   private Expression expr2 = null;

   public OrExpression(Expression expr1, Expression expr2) {
      this.expr1 = expr1;
      this.expr2 = expr2;
   }

   @Override
   public boolean interpret(String context) {
      return expr1.interpret(context) || expr2.interpret(context);
   }
}

AndExpression.java

public class AndExpression implements Expression {

   private Expression expr1 = null;
   private Expression expr2 = null;

   public AndExpression(Expression expr1, Expression expr2) {
      this.expr1 = expr1;
      this.expr2 = expr2;
   }

   @Override
   public boolean interpret(String context) {
      return expr1.interpret(context) && expr2.interpret(context);
   }
}

InterpreterPatternDemo.java

public class InterpreterPatternDemo {

   public static Expression getMaleExpression(){
      Expression robert = new TerminalExpression("Robert");
      Expression john = new TerminalExpression("John");
      return new OrExpression(robert, john);
   }

   public static Expression getMarriedWomanExpression(){
      Expression julie = new TerminalExpression("Julie");
      Expression married = new TerminalExpression("Married");
      return new AndExpression(julie, married);
   }

   public static void main(String[] args) {
      Expression isMale = getMaleExpression();
      Expression isMarriedWoman = getMarriedWomanExpression();

      System.out.println("John is male? " + isMale.interpret("John"));
      System.out.println("Julie is a married women? "
      + isMarriedWoman.interpret("Married Julie"));
   }
}

输出结果:

John is male? true
Julie is a married women? true

JDK源码中的使用场景

在JDK源码中的Pattern对正则表达式的编译和解析就体现到了解析器模式

23种设计模式之解释器模式(Interpreter)
private void compile() {

        if (has(CANON_EQ) && !has(LITERAL)) {
            normalize();
        } else {
            normalizedPattern = pattern;
        }
        patternLength = normalizedPattern.length();

        temp = new int[patternLength + 2];

        hasSupplementary = false;
        int c, count = 0;

        for (int x = 0; x < patternLength; x += Character.charCount(c)) {
            c = normalizedPattern.codePointAt(x);
            if (isSupplementary(c)) {
                hasSupplementary = true;
            }
            temp[count++] = c;
        }

        patternLength = count;

        if (! has(LITERAL))
            RemoveQEQuoting();

        buffer = new int[32];
        groupNodes = new GroupHead[10];
        namedGroups = null;

        if (has(LITERAL)) {

            matchRoot = newSlice(temp, patternLength, hasSupplementary);
            matchRoot.next = lastAccept;
        } else {

            matchRoot = expr(lastAccept);

            if (patternLength != cursor) {
                if (peek() == ')') {
                    throw error("Unmatched closing ')'");
                } else {
                    throw error("Unexpected internal error");
                }
            }
        }

        if (matchRoot instanceof Slice) {
            root = BnM.optimize(matchRoot);
            if (root == matchRoot) {
                root = hasSupplementary ? new StartS(matchRoot) : new Start(matchRoot);
            }
        } else if (matchRoot instanceof Begin || matchRoot instanceof First) {
            root = matchRoot;
        } else {
            root = hasSupplementary ? new StartS(matchRoot) : new Start(matchRoot);
        }

        temp = null;
        buffer = null;
        groupNodes = null;
        patternLength = 0;
        compiled = true;
    }

    Map<String, Integer> namedGroups() {
        if (namedGroups == null)
            namedGroups = new HashMap<>(2);
        return namedGroups;
    }
private Pattern(String p, int f) {

        pattern = p;
        flags = f;

        if ((flags & UNICODE_CHARACTER_CLASS) != 0)
            flags |= UNICODE_CASE;

        capturingGroupCount = 1;
        localCount = 0;

        if (pattern.length() > 0) {

            compile();
        } else {
            root = new Start(lastAccept);
            matchRoot = lastAccept;
        }
    }

总结

优点: 1、可扩展性比较好,灵活。 2、增加了新的解释表达式的方式。 3、易于实现简单文法。

缺点: 1、可利用场景比较少。 2、对于复杂的文法比较难维护。 3、解释器模式会引起类膨胀。 4、解释器模式采用递归调用方法。

使用场景: 1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。 2、一些重复出现的问题可以用一种简单的语言来进行表达。 3、一个简单语法需要解释的场景。

注意事项: 可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。

更多请移驾。。。
🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽
本文作者:Java技术债务
原文链接:https://www.cuizb.top/myblog/article/1661695586
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。
🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽

23种设计模式之解释器模式(Interpreter)
JVM内存泄漏和内存溢出的原因
JVM常用监控工具解释以及使用
Redis 常见面试题(一)
ClickHouse之MaterializeMySQL引擎(十)
三种实现分布式锁的实现与区别
线程池的理解以及使用
最近面试BAT,整理一份面试资料,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。想获取吗?如果你想提升自己,并且想和优秀的人一起进步,感兴趣的朋友,可以在扫码关注下方公众号。资料在公众号里静静的躺着呢。。。
  • 喜欢就收藏
  • 认同就点赞
  • 支持就关注
  • *疑问就评论

一键四连,你的offer也四连

Original: https://www.cnblogs.com/cuizb/p/16709523.html
Author: Java技术债务
Title: 23种设计模式之解释器模式(Interpreter)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/713357/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Python实现秒杀某宝商品抢购(附超详细代码)

    前言 618过去了,前两天我干了一件惊天动地的大事,估计这件大事是很多小伙伴都想干的。我居然用python抢购淘宝商品,没想到 吧,最勇敢的还是我。关于抢购的思路以及代码,我将会在…

    技术杂谈 2023年6月21日
    0118
  • 8086汇编 rep 指令

    8086汇编 rep 指令 rep指令常和串传送指令搭配使用功能:根据cx的值,重复执行后面的指令 串传送指令1: movsb 功能:(以字节为单位传送)(1) ((es)×16 …

    技术杂谈 2023年6月1日
    0102
  • 初学者必犯的10个Python错误

    前言 当我们开始学习Python时,我们会养成一些不良编码习惯,而更可怕的是我们连自己也不知道。 我们学习变成的过程中,大概有会这样的经历: 写的代码只能完成了一次工作,但后来再执…

    技术杂谈 2023年6月21日
    0103
  • Map–部分方法

    1.Map.values()方法:获取Map集合中的所有键值对象 获取 Map 集合中的所有键值对象,这些键值对象将存放在另一个集合对象中 2.getOrDefault() 方法 …

    技术杂谈 2023年7月24日
    084
  • SpringBoot教程,吃透这些知识点,超过90%的Java面试者

    动力节点王鹤老师的SpringBoot入门系列课程,通俗易懂,基于SpringBoot2.4版本讲解。 从细节入手,每个事例先讲解pom.xml中的重要依赖,其次applicati…

    技术杂谈 2023年7月25日
    070
  • AtCoder Beginner Contest 235

    AtCoder Beginner Contest 235 A – Rotate 思路分析: 因为他给的数是三位数,我们直接取出每一位,然后拼凑就可以了 代码如下: #i…

    技术杂谈 2023年7月24日
    073
  • Python 周期任务神器,太实用了

    前言 如果你想在Linux服务器上周期性地执行某个 Python 脚本,最出名的选择应该是 Crontab 脚本,但是 Crontab 具有以下缺点: 1.不方便执行秒级的任务。 …

    技术杂谈 2023年6月21日
    0107
  • Linux Accounting(中文翻译)(1):Pressure Stall Information

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    技术杂谈 2023年7月11日
    073
  • 零食里的营养成分表百分比什么意思

    原文: http://www.nhc.gov.cn/ewebeditor/uploadfile/2013/02/20130204161215710.pdf 来看看花生的: Orig…

    技术杂谈 2023年5月31日
    0104
  • [转帖]Apache Ignite(六):Ignite 的集群部署

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    技术杂谈 2023年5月30日
    081
  • QGIS的编译 (Windows)

    一、资源 https://github.com/qgis/QGIS https://github.com/qgis/QGIS/blob/master/INSTALL.md 二、编译…

    技术杂谈 2023年5月31日
    098
  • RDD(弹性分布式数据集)及常用算子

    RDD(弹性分布式数据集)及常用算子 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是 Spark 中最基本的数据 处理模型。代码中是一…

    技术杂谈 2023年7月11日
    075
  • 手把手教你:人脸识别考勤系统

    系列文章 手把手教你:人脸识别考勤系统 本文为系列第一篇 @ 系列文章 项目简介 一、项目展示 二、环境需求 环境安装实例 三、功能模块介绍 1.人脸库图像 2.构建人脸库 3.启…

    技术杂谈 2023年7月25日
    072
  • 立体角

    【 立体角】 1、球坐标中,每一个方向可以用两个角来表示,方位角、仰角。这两个角定义了球中惟一的方向, Θ(φ,θ)。 φ和 θ 在一个指定的区间内。 2、立体角是以圆锥体的顶点为…

    技术杂谈 2023年5月31日
    091
  • 接口和抽象类是否有构造方法

    先上结论: 接口没有,抽象类可以有。 甚至于有其他的区别: 接口不能有方法体,抽象类可以有 (仅限java8以前) 接口不能有静态方法,抽象类可以有 (仅限java8以前) 接口中…

    技术杂谈 2023年7月25日
    055
  • C++ 模板概念讲解及编译避坑

    C++ 不同于 Java,它没有标准的 Object 类型。也就意味着 C++ 并不存在完整的泛型编程概念。 为什么不存在完整的泛型编程概念,放到最后一个例子讲,先讲 &#8220…

    技术杂谈 2023年6月21日
    090
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球