Java设计模式(二十三)----解释器模式

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


解释器模式的结构
下面就以一个示意性的系统为例,讨论解释器模式的结构。系统的结构图如下所示:

这里写图片描述

  模式所涉及的角色如下所示:
  (1)抽象表达式(Expression)角色:声明一个所有的具体表达式角色都需要实现的抽象接口。这个接口主要是一个interpret()方法,称做解释操作。
  (2)终结符表达式(Terminal Expression)角色:实现了抽象表达式角色所要求的接口,主要是一个interpret()方法;文法中的每一个终结符都有一个具体终结表达式与之相对应。比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
  (3)非终结符表达式(Nonterminal Expression)角色:文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,“+”就是非终结符,解析“+”的解释器就是一个非终结符表达式。
  (4)环境(Context)角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。

具体案例

//上下文环境角色
public class Context {
     private Map<Variable,Integer> valueMap = new HashMap<Variable,Integer>();  

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

     public int LookupValue(Variable x)  

     {  
            int i = valueMap.get(x);  
            return i ;  
     }  
}

//抽象表达式角色,也可以用接口来实现  
public abstract class Expression {
    public abstract int interpret(Context con);
}

//终结符表达式角色 
public class Constant extends Expression {
    private int i;
    public Constant(int i){
        this.i = i;
    }

    public int interpret(Context con){
        return i;
    }
}

public class Variable  extends Expression{
    public int interpret(Context con)

    {

        // this为调用interpret方法的Variable对象

        return con.LookupValue(this);

    }
}

//非终结符表达式角色 
public class Add extends Expression {
    private Expression left, right;

    public Add(Expression left, Expression right)

    {

        this.left = left;

        this.right = right;

    }

    public int interpret(Context con)

    {

        return left.interpret(con) + right.interpret(con);

    }

}

public class Subtract  extends Expression {
    private Expression left, right;

    public Subtract(Expression left, Expression right)

    {

        this.left = left;

        this.right = right;

    }


    public int interpret(Context con)

    {

        return left.interpret(con) - right.interpret(con);

    }
}

public class Multiply extends Expression {
    private Expression left, right;

    public Multiply(Expression left, Expression right)

    {

        this.left = left;

        this.right = right;

    }

    public int interpret(Context con)

    {

        return left.interpret(con) * right.interpret(con);

    }
}

public class Division  extends Expression{
    private Expression left, right;

    public Division(Expression left, Expression right)

    {

        this.left = left;

        this.right = right;

    }

    public int interpret(Context con)

    {

        try {

            return left.interpret(con) / right.interpret(con);

        } catch (ArithmeticException ae)

        {

            System.out.println("被除数为0!");

            return -11111;

        }

    }
}

//测试程序,计算 (a*b)/(a-b+2)  
public class Test {
    private static Expression ex,exa,exs,exm;

    private static Context con;

    public static void main(String[] args)

    {

        con = new Context();

        // 设置变量、常量

        Variable a = new Variable();

        Variable b = new Variable();

        Constant c = new Constant(2);

        // 为变量赋值

        con.addValue(a, 10);

        con.addValue(b, 8);


        // 运算,对句子的结构由我们自己来分析,构造
        exs=new Subtract(a, b);
        exa=new Add(exs, c);
        exm=new Multiply(a, b);
        ex = new Division(exm, exa);

        System.out.println("运算结果为:" + ex.interpret(con));

    }
}

优缺点
解释器模式提供了一个简单的方式来执行语法,而且容易修改或者扩展语法。一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。而且在解释器中不同的规则是由不同的类来实现的,这样使得添加一个新的语法规则变得简单。
但是解释器模式对于复杂文法难以维护。可以想象一下,每一个规则要对应一个处理类,而且这些类还要递归调用抽象表达式角色,多如乱麻的类交织在一起是多么恐怖的一件事啊!

以上内容来自平时所看书籍和网络资源整理测试所得,如有不完善之处,欢迎指正!

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值