解释器模式(INTERPRETER),通过面向对象的方式构造语言解释器,并使用该解释器按照一定的文法解释语言中的句子,属于类行为模式。记得大学时候参加过机器人足球比赛,通过面板输入指令"up move 10 and left run 8",足球机器人就会执行相应的动作。将这些指令组合就能完成高难度的射门,躲避,可谓智能也!下面将通过机器人指令解释来阐述解释器模式的强大。
一、使用场景
1、当有一个语言需要解释执行,并能从该语言的句子中抽象出语法树时,比如机器人足球比赛的指令,也就up,down,move等有限的基础操作码。
2、抽象出的文法要简单,不至于导致文法的类层次过于庞大而无法管理。对于复杂的文法可以使用语法分析程序生成器,这样无需构造抽象语法树,节省时间和空间。
3、效率不是关键的情况。高效的解释器通常不采用直接解释抽象语法树实现,而是通过转换其他形式实现,比如状态机。
二、UML图
三、Java实现
- package study.patterns.interpreter;
-
- import java.util.Stack;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public class InterpreterPattern {
- public static void main(String[] args) {
- String sentence = "up move 8 and right run 10 and left move 6";
- InstructionHandler handler = new InstructionHandler();
- handler.handle(sentence);
- System.out.println(handler.interpret());
- }
- }
-
-
-
- interface INode{
- public String interpret();
- }
-
-
-
- class AndNode implements INode{
- private INode left;
- private INode right;
-
- public AndNode(INode left,INode right){
- this.left = left;
- this.right = right;
- }
-
-
-
-
- @Override
- public String interpret() {
- return left.interpret()+"再"+right.interpret();
- }
- }
-
-
-
- class SentenceNode implements INode{
- private INode direction;
- private INode action;
- private INode distance;
-
- public SentenceNode(INode direction,INode action,INode distance){
- this.direction = direction;
- this.action = action;
- this.distance = distance;
- }
-
-
-
-
- @Override
- public String interpret() {
- return direction.interpret()+action.interpret()+distance.interpret();
- }
- }
-
-
-
- class DirectionNode implements INode{
- private String direction;
-
- public DirectionNode(String direction){
- this.direction = direction;
- }
-
-
-
-
- @Override
- public String interpret() {
- 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 "无效操作码";
- }
- }
- }
-
-
-
-
- class ActionNode implements INode{
- private String action;
-
- public ActionNode(String action){
- this.action = action;
- }
-
-
-
-
- @Override
- public String interpret() {
- if(action.equalsIgnoreCase("move")){
- return "移动";
- }else if(action.equalsIgnoreCase("run")){
- return "快速移动";
- }else{
- return "无效操作码";
- }
- }
- }
-
-
-
-
- class DistanceNode implements INode{
- private String distance;
-
- public DistanceNode(String distance){
- this.distance = distance;
- }
-
- @Override
- public String interpret() {
- return distance;
- }
- }
-
-
-
-
- class InstructionHandler{
- private INode node;
-
- public void handle(String sentence){
- INode left=null,right=null,direction=null,action=null,distance=null;
- Stack<INode> stack = new Stack<INode>();
- String[] words = sentence.split(" ");
- for(int i=0; i<words.length; i++){
-
-
- if(words[i].equalsIgnoreCase("and")){
- left = stack.pop();
- String word1 = words[++i];
- direction = new DirectionNode(word1);
- String word2 = words[++i];
- action = new ActionNode(word2);
- String word3 = words[++i];
- distance = new DistanceNode(word3);
- right = new SentenceNode(direction, action, distance);
- stack.push(new AndNode(left, right));
- }
-
- else{
- String word1 = words[i];
- direction = new DirectionNode(word1);
- String word2 = words[++i];
- action = new ActionNode(word2);
- String word3 = words[++i];
- distance = new DistanceNode(word3);
- left = new SentenceNode(direction, action, distance);
- stack.push(left);
- }
- }
- this.node = (INode) stack.pop();
- }
-
- public String interpret(){
- return node.interpret();
- }
- }
运行结果:
四、模式优缺点
优点:
1、易于改变和扩展文法。由于解释器模式采用类来表示文法规则,可以通过继承来改变或扩展原有文法。
2、易于实现文法。定义抽象语法树中的各个节点的类实现相似,易于直接编写,也方便采用编译器或语法分析生成器自动生成。
2、方便添加新的解释表达式。你可以在表达式类上定义新的操作以支持优美打印或表达式类型检查,优化,代码生成等,通常结合Visitor模式更佳。
缺点:
1、复杂的文法难以维护。复杂的文法会导致类层次的庞大,从而难以管理。此时可以采用编译器或语法分析程序来实现语法的解释。