折腾Java设计模式之解释器模

解释器模式

解释器模式是类的行为模式。给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。

意图 给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

主要解决 对于一些固定文法构建一个解释句子的解释器。

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

如何解决 构件语法树,定义终结符与非终结符。

关键代码 构件环境类,包含解释器之外的一些全局信息,一般是 HashMap。

解释器模式相关UML图

类图

可以看出右侧的协作图(object collaboration diagram)展现出运行时的解释器模式。Client向右侧抽象语法树发送解释请求,请求被转发并向下到树结构的所有对象。

解释器模式的主要角色

抽象解释器(AbstractExpression/Expression):声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpret()方法,称为解释操作。具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器NonterminalExpression完成。

终结符表达式(TerminalExpression):实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。终结符一半是文法中的运算单元,比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。

非终结符表达式(NonterminalExpression):文法中的每条规则对应于一个非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。

环境角色(Context):这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。

干货代码

跳转到源码地址

简单的一个解释器计算加减乘除算法,环境上下文没有用好,其实计算规则更多的是人为设定的了。

本次的抽象接收器用的是抽象类,用接口代替也可以。

//抽象解释器
public abstract class AbstractExpression {

    public abstract int interpreter(Context context);
}

//非终结表达式:加法
@Data
@AllArgsConstructor
public class Add extends AbstractExpression {

    private final AbstractExpression left;

    private final AbstractExpression right;

    @Override
    public int interpreter(Context context) {
        return left.interpreter(context) + right.interpreter(context);
    }
}

//非终结表达式:减法
@Data
@AllArgsConstructor
public class Subtract extends AbstractExpression {

    private final AbstractExpression left;

    private final AbstractExpression right;

    @Override
    public int interpreter(Context context) {
        return left.interpreter(context) - right.interpreter(context);
    }
}

//非终结表达式:乘法
@Data
@AllArgsConstructor
public class Multiply extends AbstractExpression {

    private final AbstractExpression left;

    private final AbstractExpression right;

    @Override
    public int interpreter(Context context) {
        return left.interpreter(context) * right.interpreter(context);
    }
}

//非终结表达式:除法
@Data
@AllArgsConstructor
public class Division extends AbstractExpression {

    private final AbstractExpression left;

    private final AbstractExpression right;

    @Override
    public int interpreter(Context context) {
        int right = this.right.interpreter(context);
        if (right != 0) {
            return left.interpreter(context) / right;
        }

        return -1;
    }
}

//终结表达式:变量
@Data
@AllArgsConstructor
public class Variable extends AbstractExpression {

    private final String key;

    @Override
    public int interpreter(Context context) {
        return context.getValue(key);
    }
}

//环境上下文
@Getter
public class Context {

    private final Map<String, Integer> valueMap = Maps.newHashMap();

    public void addValue(final String key, final int value) {
        valueMap.put(key, Integer.valueOf(value));
    }

    public int getValue(final String key) {
        return valueMap.get(key).intValue();
    }
}

//
public class Application {

    public static void main(String[] args) {
        Context context = new Context();
        context.addValue("a", 6);
        context.addValue("b", 9);
        context.addValue("c", 1);

        Variable a = new Variable("a");
        Variable b = new Variable("b");
        Variable c = new Variable("c");

        AbstractExpression multiplyValue = new Multiply(a, b);
        AbstractExpression subtractValue = new Subtract(a, b);
        AbstractExpression addValue = new Add(subtractValue, c);
        AbstractExpression divisionValue = new Division(multiplyValue, addValue);

        log.info("{}", context.getValueMap());
        log.info("(a*b)/(a-b+c) = {}", divisionValue.interpreter(context));
    }
}

结果如下:

Java中的应用

java中的表达式引擎

parsii

JEval

JEPLite

expr

Janino

MathEval

Java表达式引擎fel/groovy/expression4j/java脚本引擎的性能对比

JDK中的应用

这个模式通常定义了一个语言的语法,然后解析相应语法的语句。

java.util.Pattern

java.text.Normalizer

java.text.Format

参考

解释器模式|菜鸟教程

Interpreter pattern

细数JDK里的设计模式

23种设计模式(14):解释器模式

原文地址:https://www.cnblogs.com/damonchow/p/10271021.html

时间: 2024-11-09 15:08:58

折腾Java设计模式之解释器模的相关文章

折腾Java设计模式之解释器模式

解释器模式 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 意图 给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子. 主要解决 对于一些固定文法构建一个解释句子的解释器. 何时使用 如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子.这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题. 如何解

折腾Java设计模式之备忘录模式

原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's internal state allowing the object to be restored to this state later. 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态. 所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个

折腾Java设计模式之中介者模式

博文原址:折腾Java设计模式之中介者模式 中介者模式 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性.这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护.中介者模式属于行为型模式. 通俗点来讲就是提供一个中介平台,说到平台,那其实很容易联系到我们很熟悉的房地产中介.我们可以直接通过这个平台得到我们想要的信息,不用对象自身与其他对象交互. 买房子租房子就不需要去找房东,只需要在中介那里获取相应的×××信息.如下图那样,两方只

折腾Java设计模式之单例模式

博文原址:折腾Java设计模式之单例模式 单例模式 Ensure a class has only one instance, and provide a global point of access to it. 一个类仅仅只有一个实例,并且提供全局的接入点.简洁点理解就是涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建.这个类提供了一种访问它自己唯一的对象的方式,可以直接访问,不需要实例化该类的对象. 饿汉式单例模式 public final class EagerSi

折腾Java设计模式之迭代器模式

迭代器模式 Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. 提供一种不公示其底层细节(结构)的情况下能顺序访问聚合对象元素的方法. 其实在java体系中,jdk已经引入了迭代器接口以及对于的容器接口等.就拿迭代器中的角色,在java中找出其对应的类. 具体角色 (1)迭代器角色(Iterator):定义遍

JAVA设计模式之解释器模式

在阎宏博士的<JAVA与模式>一书中开头是这样描述解释器(Interpreter)模式的: 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 解释器模式的结构 下面就以一个示意性的系统为例,讨论解释器模式的结构.系统的结构图如下所示: 模式所涉及的角色如下所示: (1)抽象表达式(Expression)角色:声明一个所有的具体表达式角色都需要实现的抽象接口.这个接口主要是一个interpre

折腾Java设计模式之策略模式

博客原文地址 简介 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式.简单理解就是一组算法,可以互换,再简单点策略就是封装算法. 意图 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换. 主要解决 在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护. 何时使用 一个系统有许多许多类,而区分它们的只是他们直接的行为. 如何解决 将这些算法封装成一个一个的类,任意地替换. 主要角色 上下文C

折腾Java设计模式之观察者模式

观察者模式 Define a one-to-many dependency between objects where a state change in one object results in all its dependents being notified and updated automatically. 直译过来就是,定义对象间的一对多依赖关系,当一个对象的状态变更会自动通知和更新所有依赖项.像发布/订阅模式,事件通知模式,数据源/监听模式等都是性质一样. 观察者模式UML UM

大话设计模式_解释器模式(Java代码)

解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 简单描述:一个AbstractExpression类,多个子类,存在一个Interpret方法,转义Context对象的信息.客户端根据信息实例化不同的Expression类,并调用其转义方法(这个过程可以使用简单工厂+反射进行) 大话设计模式中的截图: 代码例子: 假设HTML代码解释器: (1)第一类标签<HTML>(开始)/<HEAD>(头信息)/<BODY&g