• 设计模式之解释器模式


    解释器模式字面意思,也即解释某些内容的含义。这种设计模式是实际开发中最不容易用到的。比如SQL解析,符号处理引擎,会用到解释器模式,属于更底层的开发人员才会用到的设计模式。

    本文就以解释器模式的概念、角色和简单的例子说明解释器模式,读者对这部分内容了解即可。

    一、概念

    解释器模式是指给定一门语言,定义它的文法的一种表示(如:加减乘除表达式和正则表达式等),然后再定义一个解释器,该解释器用来解释我们的文法表示(表达式)。

    解释器模式的结构与组合模式相似,不过其包含的组成元素比组合模式多,而且组合模式是对象结构型模式,而解释器模式是类行为型模式。

    解释器模式中包含四个角色:

    1. 抽象解释器(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。

    2. 终结符解释器(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。

    3. 非终结符解释器(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。

    4. 环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。

      解释器模式类结构图如图所示:

    image-20220906145121375

    二、实现

    接下来针对四个角色分别定义他们的实现。

    抽象解释器:

    /**
     * 声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享
     * @author tcy
     * @Date 29-08-2022
     */
    public abstract class AbstractExpression {
    
        public abstract boolean interpret(String info);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    非终结符表达式:

    /**
     * 非终结符表达式,为文法中的非终结符实现解释操作。对文法中每一条规则R1、R2...Rn都需要一个具体的非终结符表达式类
     * @author tcy
     * @Date 29-08-2022
     */
    public class NonTerminalExpression extends AbstractExpression{
    
        private AbstractExpression address=null;
        private AbstractExpression name=null;
        private AbstractExpression id=null;
    
        public NonTerminalExpression(AbstractExpression address, AbstractExpression name, AbstractExpression id) {
            this.address = address;
            this.name = name;
            this.id = id;
        }
    
    
        @Override
        public boolean interpret(String info) {
            String s[]=info.split("-");
            return address.interpret(s[0])&&name.interpret(s[1])&&id.interpret(s[2]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    终结符表达式:

    **
     * 实现与文法中的终结符相关联的解释操作,文法中每一个终结符都有一个具体终结表达式与之相对应
     * @author tcy
     * @Date 29-08-2022
     */
    public class TerminalExpression extends AbstractExpression{
    
        private Set set =new HashSet();
    
        public TerminalExpression(String[] data)
        {
            for(int i=0; i
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    上下文环境:

    /**
     * 上下文环境
     * @author tcy
     * @Date 29-08-2022
     */
    public class Context {
        private String[] shuzis={"1","2","3","4","5","6","7","8","9","0"};
        private String[] xiaoxiezimus={"a","b","c","d","e","f","g","h","i","j","k","l"};
        private String[] daxiezimus={"A","B","C","D","E","F","G"};
        private AbstractExpression infomation;
    
        public Context()
        {
            AbstractExpression shuzi=new TerminalExpression(shuzis);
            AbstractExpression xiaoxiezimu=new TerminalExpression(xiaoxiezimus);
            AbstractExpression daxiezimu=new TerminalExpression(daxiezimus);
            infomation=new NonTerminalExpression(shuzi,xiaoxiezimu,daxiezimu);
        }
    
        public void jieshi(String info)
        {
            boolean ok=infomation.interpret(info);
            if(ok) System.out.println("正确! ["+info+"] 满足  [单个数字-单个小写-单个大写]  的条件");
            else System.out.println("错误! ["+info+"] 不满足  [单个数字-单个小写-单个大写]  的条件");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    客户端:

    /**
     * @author tcy
     * @Date 29-08-2022
     */
    public class Client {
        public static void main(String[] args) {
            Context people=new Context();
            people.jieshi("2-a-A");
            people.jieshi("11-A-5");
            people.jieshi("你-好-吖");
            people.jieshi("2aA");
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    以上为解释器模式的简单案例,读者可以拉取代码到本地进行学习。

    三、应用场景

    解释器模式在实际的软件开发中使用比较少,因为它会引起效率、性能以及维护等问题。

    在JDK中的正则表达式中的Pattern类和Spring里面的ExpressionParse接口使用的是解释器模式的思想。

    当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候,如 XML 文档解释,整体来说还是一种应用较少的设计模式。

    已经连续更新了数十篇设计模式博客,推荐你结合学习。

    一、设计模式概述

    二、设计模式之工厂方法和抽象工厂

    三、设计模式之单例和原型

    四、设计模式之建造者模式

    五、设计模式之代理模式

    六、设计模式之适配器模式

    七、设计模式之桥接模式

    八、设计模式之组合模式

    九、设计模式之装饰器模式

    十、设计模式之外观模式

    十一、外观模式之享元模式

    十二、设计模式之责任链模式

    十三、设计模式之命令模式

  • 相关阅读:
    JEECG shiro验证实现分析
    Vite和Webpack区别
    规则引擎集成新的可观测性框架
    VMware虚拟机安装CentOS Linux操作系统
    普华永道与 OpenAI 合作,为10万员工提供 ChatGPT 服务
    JMeter添加插件
    LLVM学习笔记(49)
    优化算法|MOAVOA:一种新的多目标人工秃鹰优化算法(Matlab代码实现)
    肖sir___环境的讲解详情__002
    OpenHarmony 4.0 Release 编译异常处理
  • 原文地址:https://blog.csdn.net/weixin_44643680/article/details/126726756