把书读薄 | 《设计模式之美》设计模式与范式(行为型-解释器模式)(上)

简介: 本文对应设计模式与范式:行为型(72),解释器模式 (Interpreter Pattern),用来描述如何构建一个简单的 "语言"解释器。

0x0、引言


本文对应设计模式与范式:行为型(72),解释器模式 (Interpreter Pattern),用来描述如何构建一个简单的 "语言"解释器


比命令模式更小众,只有在特定领域才会用到,如编译器、规则引擎、正则表达式、SQL等,而这类语言又称 领域特定语言 (Domain Specific Language, DSL)。


工作中很少会让我们去编写一个解释器,了解下即可,主要是借鉴思想 如何通过更简洁的规则来表示复杂逻辑


Tips:二手知识加工难免有所纰漏,感兴趣有时间的可自行查阅原文,谢谢。


0x1、定义


原始定义


为某个语言定义它的语法(文法)表示,并定义一个解释器用来处理这个语法。


有点懵逼,没事,先来看下它的四个组成角色:


  • AbstractExpression (抽象表达式) → 定义一个解释器有哪些 解释操作,具体类实现还分 终结符解释器非终结符解释器


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


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


  • Context (上下文环境) → 存放各个终结符对应的具体值,还是R=R1+R2,给R1赋值100,给R2赋值200,这些信息需存放到环境角色中,很多情况下使用Map充当环境角色就够了~


直接画出UML类图


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


0x2、写个简单例子


定义一个能解释加减法的解释器为例子~


// 抽象表达式
public abstract class AbstractExpression {
    public abstract int interpreter(Context context);
    @Override abstract public String toString();
}
// 上下文环境
public class Context {
    private Map<AbstractExpression, Integer> map = new HashMap<>();
    public void addExpression(AbstractExpression expression, int value) {
        map.put(expression, value);
    }
    public int lookup(AbstractExpression expression) { 
        return map.get(expression);
    }
}
// 终结符表达式(常量与变量)
public class ConstantExpression extends AbstractExpression {
    private int value;
    public ConstantExpression(int value) {
        this.value = value;
    }
    @Override
    public int interpreter(Context context) {
        return value;
    }
    @Override
    public String toString() {
        return Integer.toString(value);
    }
}
public class VariableExpression extends AbstractExpression {
    private String name;
    public VariableExpression(String name) {
        this.name = name;
    }
    @Override
    public int interpreter(Context context) {
        return context.lookup(this);
    }
    @Override
    public String toString() {
        return name;
    }
}
// 非终结符表达式(加法和减法)
public class PlusExpression extends AbstractExpression {
    private final AbstractExpression leftExpression;
    private final AbstractExpression rightExpression;
    public PlusExpression(AbstractExpression leftExpression, AbstractExpression rightExpression) {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }
    @Override
    public int interpreter(Context context) {
        return leftExpression.interpreter(context) + rightExpression.interpreter(context);
    }
    @Override
    public String toString() {
        return leftExpression.toString() + " + " + rightExpression.toString();
    }
}
public class MinusExpression extends AbstractExpression {
    private final AbstractExpression leftExpression;
    private final AbstractExpression rightExpression;
    public MinusExpression(AbstractExpression leftExpression, AbstractExpression rightExpression) {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }
    @Override
    public int interpreter(Context context) {
        return leftExpression.interpreter(context) - rightExpression.interpreter(context);
    }
    @Override
    public String toString() {
        return leftExpression.toString() + " - " + rightExpression.toString();
    }
}
// 测试用例
public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        AbstractExpression a = new VariableExpression("a");
        AbstractExpression b = new VariableExpression("b");
        AbstractExpression c = new VariableExpression("c");
        context.addExpression(a, 6);
        context.addExpression(b, 8);
        context.addExpression(c, 16);
        AbstractExpression e1 = new PlusExpression(a, b);
        System.out.println(e1 + " = " + e1.interpreter(context));
        AbstractExpression e2 = new PlusExpression(e1, c);
        System.out.println(e2 + " = " + e2.interpreter(context));
        AbstractExpression e3 = new MinusExpression(e2, new ConstantExpression(7));
        System.out.println(e3 + " = " + e3.interpreter(context));
        AbstractExpression e4 = new MinusExpression(e3, b);
        System.out.println(e4 + " = " + e4.interpreter(context));
    }
}


相关文章
|
3月前
|
设计模式 算法
行为型设计模式之模板模式
行为型设计模式之模板模式
|
3月前
|
设计模式 存储
行为型设计模式之观察者模式
行为型设计模式之观察者模式
|
3月前
|
设计模式 算法
行为型设计模式
行为型设计模式
|
4月前
|
设计模式 SQL Java
【设计模式】抖音一面:你不知道解释器模式?
【设计模式】抖音一面:你不知道解释器模式?
39 1
|
4月前
|
设计模式 Go
[设计模式 Go实现] 行为型~状态模式
[设计模式 Go实现] 行为型~状态模式
|
4月前
|
设计模式 Go
[设计模式 Go实现] 行为型~迭代器模式
[设计模式 Go实现] 行为型~迭代器模式
|
4月前
|
设计模式 存储 Go
[设计模式 Go实现] 行为型~备忘录模式
[设计模式 Go实现] 行为型~备忘录模式
|
4月前
|
设计模式 Go
[设计模式 Go实现] 行为型~模板方法模式
[设计模式 Go实现] 行为型~模板方法模式
|
4月前
|
设计模式 Go
[设计模式 Go实现] 行为型~职责链模式
[设计模式 Go实现] 行为型~职责链模式
|
4月前
|
设计模式 Go
[设计模式 Go实现] 行为型~解释器模式
[设计模式 Go实现] 行为型~解释器模式