行为型模式 - 解释器模式(Interpreter Pattern)

简介: 行为型模式 - 解释器模式(Interpreter Pattern)

一、解释器模式概述

如下图,设计一个软件用来进行加减计算。我们第一想法就是使用工具类,提供对应的加法和减法的工具方法。

网络异常,图片无法展示
|

//用于两个整数相加
public static int add(int a,int b){
    return a + b;
}
//用于两个整数相加
public static int add(int a,int b,int c){
    return a + b + c;
}
//用于n个整数相加
public static int add(Integer ... arr) {
    int sum = 0;
    for (Integer i : arr) {
        sum += i;
    }
    return sum;
}

上面的形式比较单一、有限,如果形式变化非常多,这就不符合要求,因为加法和减法运算,两个运算符与数值可以有无限种组合方式。比如 1+2+3+4+5、1+2+3-4等等。 显然,现在需要一种翻译识别机器,能够解析由数字以及 + - 符号构成的合法的运算序列。如果把运算符和数字都看作节点的话,能够逐个节点的进行读取解析运算,这就是解释器模式的思维。 定义:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

在解释器模式中,我们需要将待解决的问题,提取出规则,抽象为一种“语言”。比如加减法运算,规则为:由数值和+-符号组成的合法序列,“1+3-2” 就是这种语言的句子。 解释器就是要解析出来语句的含义。但是如何描述规则呢? 文法(语法)规则:文法是用于描述语言的语法结构的形式规则。

expression ::= value | plus | minus
plus ::= expression ‘+’ expression   
minus ::= expression ‘-’ expression  
value ::= integer

注意:这里的符号“::=”表示“定义为”的意思,竖线 | 表示或,左右的其中一个,引号内为字符本身,引号外为语法。 上面规则描述为 :表达式可以是一个值,也可以是plus或者minus运算,而plus和minus又是由表达式结合运算符构成,值的类型为整型数。 抽象语法树:在计算机科学中,抽象语法树(AbstractSyntaxTree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。用树形来表示符合文法规则的句子。

二、解释器模式结构

解释器模式包含以下主要角色。

  • 抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
  • 终结符表达式(Terminal  Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
  • 非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
  • 环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
  • 客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。

三、解释器模式案例实现

【例】设计实现加减法的软件 代码如下:

//抽象角色AbstractExpression
public abstract class AbstractExpression {
    public abstract int interpret(Context context);
}
//终结符表达式角色
public class Value extends AbstractExpression {
    private int value;
    public Value(int value) {
        this.value = value;
    }
    @Override
    public int interpret(Context context) {
        return value;
    }
    @Override
    public String toString() {
        return new Integer(value).toString();
    }
}
//非终结符表达式角色  加法表达式
public class Plus extends AbstractExpression {
    private AbstractExpression left;
    private AbstractExpression right;
    public Plus(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public int interpret(Context context) {
        return left.interpret(context) + right.interpret(context);
    }
    @Override
    public String toString() {
        return "(" + left.toString() + " + " + right.toString() + ")";
    }
}
///非终结符表达式角色 减法表达式
public class Minus extends AbstractExpression {
    private AbstractExpression left;
    private AbstractExpression right;
    public Minus(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public int interpret(Context context) {
        return left.interpret(context) - right.interpret(context);
    }
    @Override
    public String toString() {
        return "(" + left.toString() + " - " + right.toString() + ")";
    }
}
//终结符表达式角色 变量表达式
public class Variable extends AbstractExpression {
    private String name;
    public Variable(String name) {
        this.name = name;
    }
    @Override
    public int interpret(Context ctx) {
        return ctx.getValue(this);
    }
    @Override
    public String toString() {
        return name;
    }
}
//环境类
public class Context {
    private Map<Variable, Integer> map = new HashMap<Variable, Integer>();
    public void assign(Variable var, Integer value) {
        map.put(var, value);
    }
    public int getValue(Variable var) {
        Integer value = map.get(var);
        return value;
    }
}
//测试类
public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        Variable a = new Variable("a");
        Variable b = new Variable("b");
        Variable c = new Variable("c");
        Variable d = new Variable("d");
        Variable e = new Variable("e");
        //Value v = new Value(1);
        context.assign(a, 1);
        context.assign(b, 2);
        context.assign(c, 3);
        context.assign(d, 4);
        context.assign(e, 5);
        AbstractExpression expression = new Minus(new Plus(new Plus(new Plus(a, b), c), d), e);
        System.out.println(expression + "= " + expression.interpret(context));
    }
}

四、解释器模式优缺点

  • 优点
  • 易于改变和扩展文法。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
  • 实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂。
  • 增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合 "开闭原则"。
  • 缺点
  • 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护。
  • 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

五、解释器模式使用场景

  • 当语言的文法较为简单,且执行效率不是关键问题时。
  • 当问题重复出现,且可以用一种简单的语言来进行表达时。
  • 当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候。

后记

喜欢我的文章的朋友点点喜欢、收藏,也欢迎朋友们评论区留下你的意见和建议,恕毅在此拜谢!


相关文章
|
12月前
|
设计模式 存储 Java
解释器模式(Interpreter Pattern)
解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言文法的表示,并定义了一个解释器,用于解释语言中的句子。
71 3
|
8月前
|
设计模式 自然语言处理 机器人
认真学习设计模式之解释器模式(Interpreter Pattern)
认真学习设计模式之解释器模式(Interpreter Pattern)
62 0
|
9月前
|
设计模式 SQL Java
设计模式~解释器模式(Interpreter)-19
解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。 目录 (1)优点: (2)缺点: (3)使用场景: (4)注意事项: (5)应用实例: 代码
53 0
|
12月前
|
移动开发 算法
解释器模式(interpreter)
解释器模式(interpreter)
44 0
|
设计模式 SQL
从零开始学设计模式(二十一):解释器模式(Interpreter Pattern)
解释器模式(Interpreter Pattern)指的是给定一种语言,定义它的文法的一种表示,并定义一个解释器,这个解释器就是被用来解释这门指定语言中句子。它是一种类行为型模式。
132 0
从零开始学设计模式(二十一):解释器模式(Interpreter Pattern)
|
设计模式 监控
行为型-Interpreter
解释器模式的原理和实现 命令模式的原理解读命令模式的英文翻译是 Command Design Pattern。在 GoF 的《设计模式》一书中,它是这么定义的:
91 0
|
设计模式 SQL
【愚公系列】2021年12月 二十三种设计模式(十五)-解释器模式(Interpreter Pattern)
【愚公系列】2021年12月 二十三种设计模式(十五)-解释器模式(Interpreter Pattern)
120 0
【愚公系列】2021年12月 二十三种设计模式(十五)-解释器模式(Interpreter Pattern)
|
C#
C#设计模式之二十三解释器模式(Interpreter Pattern)【行为型】
原文:C#设计模式之二十三解释器模式(Interpreter Pattern)【行为型】 一、引言   今天我们开始讲“行为型”设计模式的第十一个模式,也是面向对象设计模式的最后一个模式,先要说明一下,其实这个模式不是最后一个模式(按Gof的排序来讲),为什么把它放在最后呢?因为我们在业务系统中写一个解释器的机会并不是很多,实践比较少,理解和应用该模式就有些困难,所以就放在最后来说。
1307 0
|
Java 编译器 设计模式