行为型模式——解释器模式

定义

解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示解释语言中的句子。
像Java C++等语言没有办法直接的解释语句,必须定义一套自己的文法规则来实现对语句的解释。解释器描述了如何如何为简单的语言定义一个文法,如何在该语言中表示一个句子,如何解释句子,如何构造一个抽象的语法树。
(如果在学习大学课程编译原理之后,学习解释器模式就会更加的容易一些)

结构

解释器模式结构图
Context是环境类也叫作上下文类,用存储解释器之外的一些全局信息,通常用它来临时存储需要解释的语句。
AbstractExpression抽象表达式类,所有终结符表达式和非终结符表达式的公共父类,声明了抽象的解释操作(interpret()方法)。
TerminalExpression终结符表达式类。
NonterminalExpression非终结符表达式类。
在解释器模式中,每一种终结符和非终结符都有一个具体的实现类,使用类表示每一条文法规则,所以系统具有良好的灵活性和可扩展性。

实现代码:

    public abstract class AbstractExpression{
    	public abstract void interpret(Context context);
    }

public class TerminalExpression extends AbstractExpression{
	public abstract void interpret(Context context){
	//终结符表达式的解释操作
	}
}
public class NonterminalExpression extends AbstractExpression{
	private AbstractExpression left;
	private AbstractExpression right;
	public NonterminalExpression(AbstractExpression left,AbstractExpression right){
		this.left = left;
		this.right = right;
	public abstract void interpret(Context context){
	//非终结符表达式的解释操作
	}
}
public class Context{
	private HashMap<String,String> map = new HashMap<>();
	public void assign(String key,String value){
		map.put(key,value);//往环境中设值
	}
	public String lookup(String key){
		return map.get(key);
	}
}
实例

某公司要开发一个机器人的控制程序,包含一些简单的英文控制指令,每一个指令对应一个表达式,一个简单的表达式由移动方向、移动方式、移动距离表示。表达式可以为一个简单的表达式也可以是一个复杂的表达式。
移动方向:up down left right
移动方式:move run
移动距离:int整数
两个简单表达式可以由and连接成一个复合表达式。

expression::=direction action distance | composite
composite::=expression 'and’expression
direction::= ‘up’ | ‘down’ | ‘left’ | ‘right’ |
action::= ‘move’ | ‘run’ |
distance::= an integer

针对以上五条文法规则,使用五个类来实现,其中终结符表达式 direction action 和 distance对应DirectionNode ActionNode Distance 非终结符对应 SentenceNode 和 AndNode

以下是机器人控制程序的抽象语法树
机器人控制程序的抽象语法树

direction = new DirectionNode(dir);
				String a = words[++i];
				action = new ActionNode(a);
				String dis = words[++i];
				distance = new DistanceNode(dis);
package interpreter;

public class AndNode extends AbstractNode {
	private AbstractNode left;
	private AbstractNode right;
	@Override
	public String interpret() {
		// TODO Auto-generated method stub
		return left.interpret() + "再" +right.interpret();
	}
	public AndNode(AbstractNode left, AbstractNode right) {
		super();
		this.left = left;
		this.right = right;
	}
}

package interpreter;

public class SentenceNode extends AbstractNode{
	private AbstractNode direction;
	private AbstractNode action;
	private AbstractNode distance;
	public SentenceNode(AbstractNode direction, AbstractNode action, AbstractNode distance) {
		super();
		this.direction = direction;
		this.action = action;
		this.distance = distance;
	}
	@Override
	public String interpret() {
		// TODO Auto-generated method stub
		return direction.interpret()+action.interpret()+distance.interpret();
	}

}

package interpreter;

public class DirectionNode extends AbstractNode{
	private String direction;
	
	public DirectionNode(String direction) {
		super();
		this.direction = direction;
	}
	@Override
	public String interpret() {
		// TODO Auto-generated method stub
		if(direction.equals("up")){
			return "向上";
		}else if(direction.equals("down")){
			return "向下";
		}else if(direction.equals("left")){
			return "向左";
		}else if(direction.equals("right")){
			return "向右";
		}else{
			return "error";
		}
	}
}

package interpreter;

public class ActionNode extends AbstractNode{
	private String action;

	public ActionNode(String action) {
		super();
		this.action = action;
	}

	@Override
	public String interpret() {
		// TODO Auto-generated method stub
		if(action.equals("move")){
			return "移动";
		}else if(action.equals("run")){
			return "快速移动";
		}else{
			return "error";
		}
		
	}
}

package interpreter;

public class DistanceNode extends AbstractNode{
	private String distance;

	public DistanceNode(String dis) {
		super();
		this.distance = dis;
	}

	@Override
	public String interpret() {
		// TODO Auto-generated method stub
		return this.distance;
	}
	
}

package interpreter;

import java.util.Stack;

public class InstructionHandler {
	private AbstractNode node;
	public void handle(String instruction){
		AbstractNode left = null;
		AbstractNode right = null;
		AbstractNode direction = null;
		AbstractNode action = null;
		AbstractNode distance = null;
		Stack<AbstractNode> stack = new Stack<>();
		String [] words = instruction.split(" ");
		for (int i = 0; i < words.length; i++) {
			if(words[i].equalsIgnoreCase("and")){
				left = (AbstractNode)stack.pop();
				String dir = words[++i];
				direction = new DirectionNode(dir);
				String a = words[++i];
				action = new ActionNode(a);
				String dis = words[++i];
				distance = new DistanceNode(dis);
				right = new SentenceNode(direction, action, distance);
				stack.push(new AndNode(left, right));
			}else{
				String dir = words[i];
				direction = new DirectionNode(dir);
				String a = words[++i];
				action = new ActionNode(a);
				String dis = words[++i];
				distance = new DistanceNode(dis);
				left = new SentenceNode(direction, action, distance);
				stack.push(left);
				
			}
		}
		this.node = (AbstractNode)stack.pop();
	}
	public String output(){
		String result = node.interpret();
		return result;
	}

}

package interpreter;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String s = "down run 10 and left move 20";
		InstructionHandler handler = new InstructionHandler();
		handler.handle(s);
		
		System.out.println(handler.output());

	}

}

应用场景

解释器模式为自定义语言的设计和实现提供了一种解决方案,用于定义一组文法规则并且通过文法规则来解释句子。但是解释器模式的使用频率不高,但是它在正则表达式、xml文档解释等领域还是广泛应用。

优点
  • 易于改变和扩展文法。
  • 每一个文法规则都可以表示一个类,因此可以方便的实现一个简单的语言。
  • 实现文法较为容易
  • 增加新的解释表达式较为方便
缺点
  • 对于复杂的文法难以维护。一条规则至少需要定义一个类,一个语言包含太多的语法规则,类的个数急剧增加,导致系统难以维护,此时可以考虑使用语法分析程序方代替解释器模式。
  • 执行效率低。解释器模式中有大量的循环和递归调用,因此在解释较为复杂的句子时速度很慢,而且代码的调试过程也较为麻烦。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值