设计模式之解释器模式

解释器模式(Interpreter Pattern):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用来解释语言中的句子。

一、解释器模式

解释器模式用来做各种各样的解释器,如正则表达式的解释器等等,其UML图如下所示:
这里写图片描述

解释器模式由以下部分组成:

抽象表达式(Expression):声明一个所有的具体表达式角色都要实现的抽象接口。该接口中的interpret()方法,称作解释操作

终结符表达式(TerminalExpression):实现抽象表达式角色所要求的接口,文法中的每一个终结符都有一个具体终结表达式与之对应。比如R=R1+R2,R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式

非终结符表达式(NonterminalExpression):文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字。比如R=R1+R2,“+”就是非终结符,解析“+”的解释器就是一个非终结符表达式

环境(Context):这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,给R1赋值1,R2赋值2,这些信息需要存放到环境中。

二、案列分析

我们用一个能够解释加减乘除四则运算的案列,学习解释器模式。
抽象表达式:

interface Expression{
    int interpret(Context context);
}

终结符表达式:常量和变量

// 常量--终结符表达式
class Constant implements  Expression{

    private int i;

    public Constant(int i) {
        this.i = i;
    }

    @Override
    public int interpret(Context context) {
        return i;
    }
}

// 变量--终结符表达式
class Variable implements Expression{

    @Override
    public int interpret(Context context) {
        return context.lookValue(this);
    }
}

非终结符表达式:加减乘除

class Add implements Expression{

    private Expression left;
    private Expression right;

    public Add(Expression left,Expression right) {
        this.left = left;
        this.right= right;
    }

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

class Sub implements Expression{

    private Expression left;
    private Expression right;

    public Sub(Expression left,Expression right) {
        this.left = left;
        this.right= right;
    }

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

class Mul implements Expression{

    private Expression left;
    private Expression right;

    public Mul(Expression left,Expression right) {
        this.left = left;
        this.right= right;
    }

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

class Div implements Expression{

    private Expression left;
    private Expression right;

    public Div(Expression left,Expression right) {
        this.left = left;
        this.right= right;
    }

    @Override
    public int interpret(Context context) {
        return left.interpret(context)/right.interpret(context);
    }
}

环境:

class Context{
    private Map valueMap=new HashMap<>();

    public void addValue(Variable x,int y){
        valueMap.put(x,y);
    }

    public int lookValue(Variable x){
        return (int)valueMap.get(x);
    }
}

客户端调用:

public class Test {
    public static void main(String[] args) {
        Context context = new Context();
        Variable a = new Variable();
        Variable b = new Variable();
        Constant c= new Constant(100);

        context.addValue(a,100);
        context.addValue(b,20);


        Expression e = new Div(new Mul(a,b),new Add(new Sub(a,b),c));
        System.out.println("result="+e.interpret(context));
    }
}

运行结果(代码亲测,可以通过):

这里写图片描述

代码地址:Interpreter

三、模式结语

解释器模式的优点

  • 易于改变和扩展文法。

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

解释器模式的应用场景

  • 当一个语言需要解释执行,并可以将该语言中的句子表示为一个抽象语法树的时候,可以考虑使用解释器模式(如XML文档解释、正则表达式等领域)。

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

  • 一个语言的文法较为简单.当执行效率不是关键和主要关心的问题时可考虑解释器模式。

欢迎大家评论留言,点击查看更多设计模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值