设计模式——解释器模式

设计模式——解释器模式,第1张

设计模式——解释器模式

今天我们来学习解释器模式,比起命令模式,解释器模式更加小众,只会在一些特定的领域会被用到,比如编译器、规则引擎、正则表达式。所以,解释器模式也不是学习的重点,稍微了解一下。

概述

解释器模式:(Interpreter Design Pattern)解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器用来处理这个语法。

今天要学习的解释器模式,其实就是用来实现根据语法规则解读“句子”的解释器。

何时使用:

  • 如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

UML 类图:


角色组成:

  1. Abstractexpression:定义解释器的接口,约定解释器的解释 *** 作。

  2. Terminalexpression:终结符解释器,用来实现语法规则中和终结符相关的 *** 作,不再包含其它的解释器,如果用组合模式来构建抽象语法树的话,就相当于组合模式中的叶子对象,可以有多种终结符解释器。

  3. Nonterminalexpression:非终结符解释器,用来实现语法规则中非终结符相关的 *** 作,通常一个解释器对应一个语法规则,可以包含其它的解释器,如果用组合模式来构建抽象语法树的话,就相当于组合模式中的组合对象,可以有多种非终结符解释器。

  4. Context:上下文,通常包含各个解释器需要的数据,或是公共的功能。

  5. Client:客户端,指的是使用解释器的客户端,通常在这里去把按照语言的语法做的表达式,转换成为使用解释器对象描述的抽象语法树,然后调用解释 *** 作。

通用代码

Context环境角色

public class Context {

    private String input;
    private String output;

    public String getInput() {
        return input;
    }
    public void setInput(String input) {
        this.input = input;
    }
    public String getOutput() {
        return output;
    }
    public void setOutput(String output) {
        this.output = output;
    }

}

抽象表达式

public abstract class Abstractexpression {
    
    public abstract void interpret(Context ctx);
}

终结符表达式

public class Terminalexpression extends Abstractexpression{
    public void interpret(Context ctx) {
       //实现与语法规则中的终结符相关联的解释 *** 作
       System.out.println("终结符表达式");
    }
}

非终结符表达式

public class Nonterminalexpression extends Abstractexpression{
    public void interpret(Context ctx) {
       //实现与语法规则中的非终结符相关联的解释 *** 作
       System.out.println("非终结符表达式");
    }
}

Client客户端

public class Client {

    public static void main(String[] args) {
        Context context = new Context();
        List list = new ArrayList<>();

        list.add(new Terminalexpression());
        list.add(new Nonterminalexpression());
        list.add(new Terminalexpression());

        for (Abstractexpression abstractexpression : list) {
            abstractexpression.Interpret(context);
        }
    }

}

其中list为一个语法容器,容纳一个具体的表达式。通常Client是一个封装类,封装的结果就是传递进来一个规范语法文件,解析器分析后产生结果并返回,避免了调用者与语法分析器的耦合关系。

结果:

终结符表达式

非终结符表达式

终结符表达式

总结

为什么会有这个解释器模式呢,从编译原理中可以受到一些启发,使用了这样的一个解释器可以在Java语言之上再定义一层语言,这种语言通过Java编写的解释器可以放到Java环境中去执行,这样如果用户的需求发生变化,比如打算做其他事情的时候,只用在自己定义的新的语言上进行修改,对于Java编写的代码不需要进行任何的修改就能在Java环境中运行,这是非常有用的。这就好像,虽然不管怎么编译,最终由中间代码生成最终代码(机器码)是依赖于相应的机器的。但是编译器却能理解高级语言和低级语言,无论高级语言的程序是怎么样编写的,编译器的代码是不用修改的,而解释器模式就是想做一个建立在Java和我们自定义语言之间的编译器。

解释器模式的代码实现比较灵活,没有固定的模板。我们前面说过,应用设计模式主要是应对代码的复杂性,解释器模式也不例外。它的代码实现的核心思想,就是将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。一般的做法是,将语法规则拆分一些小的独立的单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5564218.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-14
下一篇 2022-12-14

发表评论

登录后才能评论

评论列表(0条)

保存