一、定义

nterpreter(解释器)模式是一种特殊的设计模式,它建立一个解释器(Interpreter),对于特定的计算机程序设计语言,用来解释预先定义的文法。简单地说,Interpreter模式是一种简单的语法解释器构架。

解释器模式属于行为模式,Gof是这样定义的:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

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

二、角色

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

 三、场景展示

类图如下:

 定义抽象类

package com.ssy.wlj.interpreter;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月25日
 * 
 */
public abstract class AbstractNode {
    public abstract String interpret();
}

定义抽象类的实现类

package com.ssy.wlj.interpreter;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月25日
 * 
 */
public class ActionNode extends AbstractNode {
    private String action;
    public ActionNode(String a) {
        // TODO Auto-generated constructor stub
        this.action=a;
    }
    @Override
    public String interpret() {
        // TODO Auto-generated method stub
        if(action.equalsIgnoreCase("move")) {
            return "移动";
        }else if(action.equalsIgnoreCase("run")) {
            return "奔跑";
        }else {
        return "无效指令";
        }
    }

}
package com.ssy.wlj.interpreter;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月25日
 * 
 */
public class AndNode extends AbstractNode {

    private AbstractNode left;         //左表达式
    private AbstractNode right;        //右表达式
    
    public AndNode(AbstractNode l,AbstractNode r) {
        // TODO Auto-generated constructor stub
        this.left=l;
        this.right=r;
    }
    @Override
    public String interpret() {
        // TODO Auto-generated method stub
        return left.interpret()+"再"+right.interpret();
    }

}
package com.ssy.wlj.interpreter;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月25日
 * 
 */
public class DirectionNode extends AbstractNode {
    private String direction;
    public DirectionNode(String dir) {
        // TODO Auto-generated constructor stub
        this.direction=dir;
    }
    @Override
    public String interpret() {
        // TODO Auto-generated method stub
        if(direction.equalsIgnoreCase("up")) {
            return "向上";
        }else if(direction.equalsIgnoreCase("down")) {
            return "向下";
        }else if(direction.equalsIgnoreCase("left")) {
            return "向左";
        }else if(direction.equalsIgnoreCase("right")) {
            return "向右";
        }else {
            return "无效指令";
        }
        
    }

}
package com.ssy.wlj.interpreter;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月25日
 * 
 */
public class DistanceNode extends AbstractNode{
    private String distance;
    public DistanceNode(String d) {
        // TODO Auto-generated constructor stub
        this.distance=d;
    }
    @Override
    public String interpret() {
        // TODO Auto-generated method stub
        
        return distance;
    }

}
package com.ssy.wlj.interpreter;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月25日
 * 
 */
public class SentenceNode extends AbstractNode{
    private AbstractNode direction;
    private AbstractNode action;
    private AbstractNode distanc;
 
    public SentenceNode(AbstractNode direc,AbstractNode a,AbstractNode d) {
        // TODO Auto-generated constructor stub
        this.direction=direc;
        this.action=a;
        this.distanc=d;
    }
    @Override
    public String interpret() {
        // TODO Auto-generated method stub
        return direction.interpret()+action.interpret()+distanc.interpret();
    }

}

 

定义Handler

package com.ssy.wlj.interpreter;

import java.util.Stack;

/**
 * 类说明: 
 * @author happy
 * @since  2019年5月25日
 * 
 */
public class InstructionHandler {
    private AbstractNode node;
    public void Handle(String instruction) {
        //用栈来保存语法树。
        AbstractNode left=null,right=null;
        AbstractNode direction=null,action=null,distance=null;
        Stack<AbstractNode> stack = new Stack<AbstractNode>();
        
        //用空格分隔指令
        
        String[] word = instruction.split(" ");
        //循环
        for(int i=0;i<word.length;i++) {
            if(word[i].equalsIgnoreCase("and")) {
                left = (AbstractNode)stack.pop();
                String wordl=word[++i];
                direction = new DirectionNode(wordl);
                String word2 = word[++i];
                action = new ActionNode(word2);
                String word3 =word[++i];
                distance = new DistanceNode(word3);
                right = new SentenceNode(direction, action, distance);
                
            }else {
                String word1 = word[i];
                direction = new DirectionNode(word1);
                String word2 = word[++i];
                action = new ActionNode(word2);
                String word3 = word[++i];
                distance = new DistanceNode(word3);
                left= new SentenceNode(direction, action, distance);
                stack.push(left);
            }
        }
        this.node=(AbstractNode)stack.pop();
        
    }
    
    public String output() {
        String result = node.interpret();
        return result;
    }
}

编写客户端程序:

 

package com.ssy.wlj.interpreter;
/**
 * 类说明: 
 * @author happy
 * @since  2019年5月25日
 * 
 */
public class Client {
    public static void main(String[] args) {
        String instruction ="down run 10 and left move 20";
        InstructionHandler iHandler = new InstructionHandler();
        iHandler.Handle(instruction);
         String outString ;
         outString =iHandler.output();
         System.out.println(outString);
    }
}

解释器模式的优缺点及使用场景

优点:

  • 易于改变和扩展文法,由于在解释器模式中使用类表示语言的文法规则,因此可以通过继承等机制来改变和扩张文法。
  • 每一条文法规则都可以表示为一个类,因此可以方便地实现每一个简单的语言。
  • 实现文法比较容易。

缺点:

  • 对于复杂文法难以维护,再解释模式下每一条规则至少定义一个类,因此如果太复杂无法处理。
  • 执行效率低,由于大量使用了循环和递归。因此再解释很复杂的句子时速度很慢

使用场景:

  • 可以将一个需要解释执行的语言中的句子表示为一个抽象树。
  • 一些重复出现的问题可以用简单的语言进行表达。
  • 执行效率不是关键问题。
posted on 2019-05-25 18:33  友帅老师  阅读(122)  评论(0)    收藏  举报