首页 > 其他分享 >【设计模式】25.行为型模式-解释器(Interpreter)

【设计模式】25.行为型模式-解释器(Interpreter)

时间:2022-08-31 09:49:09浏览次数:66  
标签:25 param context interpreter Interpreter 设计模式 Expression public 表达式

一、描述

  给定一个语言,定义它的文法的一种标识,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。解释器模式为自定义语言的设计和实现提供了一种解决方案,它用于定义一组文法规则并通过这组文法规则来解释语言中的句子。

  1.角色:

  (1)抽象表达式类(AbstractExpression):定义处理文本数据的抽象方法

  (2)终点表达式类(TeminalExpression):实现抽象表达式类,为最终的叶子节点类。

  (3)非终点表达式类(UnTeminalExpression):实现抽象表达式类,并非为最终的叶子节点。

  (4)上下文(Context):包含变量与值的对应关系。

  2.类图:

 

 二、优点

  1.易于改变和扩展文法,由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。

  2.每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。

  3.实现文法比较容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。 
  4.增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式,原有表达式类代码无需修改,符合“开闭原则”

三、缺点

  1.对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。

  2.执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

四、适用场景

  1.可以将一个需要解释执行的语言中的句子表示为一个抽象语法树

  2.一些重复出现的问题可以用一种简单的语言来进行表达

  3.一个语言的文法较为简单

  4.执行效率不是关键问题

五、示例

  以“计算加减乘除为例”。代码如下:

  1.上下文类:

public class Context {
    //存储变量与值的对应关系
    private Map<String, Integer> map = new HashMap<>();

    /**
     * 添加值
     *
     * @param key
     * @param value
     */
    public void addValue(String key, Integer value) {
        map.put(key, value);
    }

    /**
     * 获取值
     */
    public Integer getValue(String key) {
        return map.get(key);
    }
}

  2.抽象表达式类

public interface Expression {
    /**
     * 定义处理上下文的接口
     *
     * @param context
     * @return
     */
    Integer interpreter(Context context);
}

  3.终端表达式类-变量类

public class Variable implements Expression {
    private String key;

    /**
     * 将变量key值赋值给当前变量
     *
     * @param key
     */
    public Variable(String key) {
        this.key = key;
    }

    /**
     * 根据key获取对应的值
     */
    @Override
    public Integer interpreter(Context context) {
        return context.getValue(key);
    }
}

  4.非终端表达式类-加法表达式

public class Add implements Expression {
    private Expression a;
    private Expression b;

    /**
     * 初始化加法符号两侧数据
     *
     * @param a
     * @param b
     */
    public Add(Expression a, Expression b) {
        this.a = a;
        this.b = b;
    }

    /**
     * 处理加法
     *
     * @param context
     * @return
     */
    @Override
    public Integer interpreter(Context context) {
        return a.interpreter(context) + b.interpreter(context);
    }
}

  5.非终端表达式-减法表达式

public class Minus implements Expression {
    private Expression a;
    private Expression b;

    /**
     * 初始化减法符号两侧数据
     *
     * @param a
     * @param b
     */
    public Minus(Expression a, Expression b) {
        this.a = a;
        this.b = b;
    }

    /**
     * 处理减法
     *
     * @param context
     * @return
     */
    @Override
    public Integer interpreter(Context context) {
        return a.interpreter(context) - b.interpreter(context);
    }
}

  6.非终端表达式-乘法表达式

public class Multiply implements Expression {
    private Expression a;
    private Expression b;

    /**
     * 初始化乘法符号两侧数据
     *
     * @param a
     * @param b
     */
    public Multiply(Expression a, Expression b) {
        this.a = a;
        this.b = b;
    }

    /**
     * 初始化乘法符号两侧数据
     */
    @Override
    public Integer interpreter(Context context) {
        return a.interpreter(context) * b.interpreter(context);
    }
}

  7.非终端表达式-除法表达式

public class Division implements Expression {
    private Expression a;
    private Expression b;

    /**
     * 初始化除法符号两侧数据
     *
     * @param a
     * @param b
     */
    public Division(Expression a, Expression b) {
        this.a = a;
        this.b = b;
    }

    /**
     * 处理除法
     */
    @Override
    public Integer interpreter(Context context) {
        return a.interpreter(context) / b.interpreter(context);
    }
}

  8.测试

public class Client {
    public static void main(String[] args) {
        //存放变量以及值对应
        Context context = new Context();
        context.addValue("a", 1);
        context.addValue("b", 2);
        context.addValue("c", 3);

        //存放变量
        Variable v1 = new Variable("a");
        Variable v2 = new Variable("b");
        Variable v3 = new Variable("c");

        //将变量添加到运算操作中
        //v1+v2
        Add add = new Add(v1, v2);
        //add - v3 = v1 + v2 - v3
        Minus minus = new Minus(add, v3);

        //计算
        System.out.println("a+b-c=" + minus.interpreter(context));
    }
}

  测试结果:

  大家有没有对这个计算流程感觉迷惑呢?接下来我解释一下这个计算流程。上面计算公式用抽象语法树表示:

  计算顺序为:

  (1) v1 + v2 = add

  (2) add - v3 = v1 + v2 - v3

  (3) 最终通过终端表达式v1,v2,v3,将变量与值换算为context中配置的具体数值,从而计算出最终结果。

标签:25,param,context,interpreter,Interpreter,设计模式,Expression,public,表达式
From: https://www.cnblogs.com/catxx/p/16261957.html

相关文章

  • 2022 年 8 月前端更新:TypeScript、软件设计模式、焦点样式和单个 CSS 转换属性中的 SO
    2022年8月前端更新:TypeScript、软件设计模式、焦点样式和单个CSS转换属性中的SOLID原则本月我们将介绍TypeScript中的SOLID原则、React应用程序的软件设计模......
  • Day25封装
    封装(数据的隐藏)通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。(该露的露,该藏的藏)程序设计要追求“高内聚,低耦合”。高内聚就是类的......
  • 静态——字段与属性、方法与类、单例设计模式
    1、static关键字static关键字,用于修饰类,字段,属性,方法,构造方法等。被static修饰的类称之为“静态类”;被static修饰的成员称之为“静态成员”;被修饰过的成员分别称为:......
  • C嵌入式编程设计模式-C语言类实现方式
    类的封装方式以文件作为封装边界,将外部调用的函数声明,全局变量变量放入头文件中,将具体实现放入.c文件中。简单栈的实现代码:/************************************......
  • PageObject(PO)设计模式在 UI 自动化中的实践总结(以 QQ 邮箱登陆为例)
    ⬇️点击“下方链接”,提升测试核心竞争力!>>更多技术文章分享和免费资料领取PO的思想最早是2013年由IT大佬MartinFlower提出的:https://martinfowler.com/bliki/PageObje......
  • 【设计模式】21.适配器模式
    说明:它是结构型的,类与类之间的桥梁,针对现有类缺什么,做个桥梁,与适合的类用上,直白点的比喻就是三个插头的插座,要加个适配器能插二个插头的。目的:一般主要做二次开发,不会在设......
  • Java之设计模式和设计原则
    一、七大原则1.1、单一职责原则1.2、里氏替换原则1.3、依赖倒置原则1.4、接口隔离原则1.5、迪米特法则1.6、开闭原则1.7、合成复用原则二、设计模式总体来说设计......
  • 设计模式之命令模式
    本文通过解决老王经常搞错借书人的问题,来引出行为型模式中的命令模式。为了在案例之上理解的更加透彻,我们需要了解命令模式在源码中的应用。最后指出命令模式的应用场景和......
  • 初识设计模式 - 工厂模式
    简介工厂设计模式(FactoryDesignPattern)是一种创建型的设计模式,它提供了一种创建对象的最佳方式,是一种代替new操作符的一种模式。在工厂模式中,创建对象不会对客户端暴......
  • 11-12-13-14-15-16-17-18-19-20-21-22-23-24-25不知道在干啥,忘了
    时间过的好快啊,已经过去了2个星期了!!!! 而我不知道都干了什么,距离玩游戏已经过去了俩星期了,不可思议,我觉得才完了三五天而已人脑子会欺骗自己的啊我想换个键盘,换个按键轻......