行为型模式之解释器模式


在软件开发中,会遇到有些问题多次重复出现,而且有一定的相似性和规律性。如果将它们归纳成一种简单的语言,那么这些问题实例将是该语言的一些句子,这样就可以用“编译原理”中的解释器模式来实现了。

虽然使用解释器模式的实例不是很多,但对于满足以上特点,且对运行效率要求不是很高的应用实例,如果用解释器模式来实现,其效果是非常好的。

解释器模式的定义

解释器(Interpreter)模式的定义:是指给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该 “表示” 来解释语言中的句子。是一种按照规定的语法(文法)进行解析的模式,属于行为型模式。

就比如编译器可以将源码编译解释为机器码,让cpu能进行识别并运行。解释器模式的作用其实与编译器一样,都是将一些固定的文法(即语法)进行解释,构建出一个解释句子的解释器。简单理解,解释器是一个简单语法分析工具,它可以识别句子语义,分离终结符号和非终结符号,提取出需要的信息,让我们能针对不同的信息作出相应的处理。其核心思想是识别文法,构建解释。

解释器模式的结构

解释器模式包含以下主要角色:
1.抽象表达式(AbstractExpression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。

2.终结符表达式(TerminalExpression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。比如:公式R=R1+R2,R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符(R1,R2)。

3.非终结符表达式(NonterminalExpression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2,解析“+”的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度增加而增加,原则上没法文法规则都对应一个非终结符表达式。

4.环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。比如:R=R1+R2,给R1赋值100,给R2赋值200,这些信息就存放到环境中。

解释器模式的实现

用解释器模式设计一个丹尼斯购物识别vip打折程序。
说明:假如是丹尼斯超市的vip购物就可以打八折,其他超市或者非vip不打折。

public class InterpreterPatternDemo {
	 public static void main(String[] args){
	        Context c=new Context();
	        c.freeRide("丹尼斯的vip用户");
	        c.freeRide("万达的vip用户");
	        c.freeRide("胖东来的vip用户");
	        c.freeRide("丹尼斯的非vip用户");
	    }
	}

	//抽象表达式类
	interface Expression{
	    public boolean interpret(String info);//解释方法
	}
	
	//终结符表达式类
	class TerminalExpression implements Expression{
		
	    private Set<String> set= new HashSet<String>();
	    
	    public TerminalExpression(String[] data){
	        for(int i=0;i<data.length;i++) {
	        	set.add(data[i]);
	        }  	
	    }
	    public boolean interpret(String info){
	        if(set.contains(info)){
	            return true;
	        }
	        return false;
	    }
	}
	//非终结符表达式类
	class AndExpression implements Expression{
	    private Expression supermarket=null;    
	    private Expression shopper=null;
	    
	    public AndExpression(Expression supermarket, Expression shopper) {
	    	this.supermarket = supermarket;
			this.shopper = shopper;
		}

		public boolean interpret(String info){
	        String s[]=info.split("的");       
	        return supermarket.interpret(s[0])&&shopper.interpret(s[1]);
	    }
	}
	
	//环境类
	class Context{
	    private String[] supermarkets={"丹尼斯"};
	    private String[] shoppers={"vip用户"};
	    private Expression expression;
	    public Context(){
	        Expression supermarket=new TerminalExpression(supermarkets);
	        Expression shopper=new TerminalExpression(shoppers);
	        expression=new AndExpression(supermarket,shopper);
	    }
	    public void freeRide(String info){
	        boolean ok = expression.interpret(info);
	        if(ok) {
	        	System.out.println("您是"+info+",您本次购物打八折!");
	        }else {
	        	System.out.println(info+",本次购物不打折!");   
	        }
	    }
}

程序运行结果如下:

您是丹尼斯的vip用户,您本次购物打八折!
万达的vip用户,本次购物不打折!
胖东来的vip用户,本次购物不打折!
丹尼斯的非vip用户,本次购物不打折!

解释器模式的应用场景

我们程序中,如果存在一种特定类型的问题,该类型问题涉及多个不同的实例,但是具备固定文法描述,那么可以使用解释器模式对该类型问题进行解释,分离出需要的信息,根据获取的信息作出相应的处理.简而言之,对于一些固定文法构建一个解释句子的解释器。适用于以下场景:
1.当语言的文法较为简单,且执行效率不是关键问题时。
2.当问题重复出现,且可以用一种简单的语言来进行表达时。
3.当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候,如 XML 文档解释。

注意:解释器模式在实际的软件开发中使用比较少,因为它会引起效率、性能以及维护等问题。

解释器模式的优缺点

优点:
1.扩展性好。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
2.容易实现。在语法树中的每个表达式节点类都是相似的,所以实现其文法较为容易。

缺点:
1.执行效率较低。解释器模式中通常使用大量的循环和递归调用,当要解释的句子较复杂时,其运行速度很慢,且代码的调试过程也比较麻烦。
2.会引起类膨胀。解释器模式中的每条规则至少需要定义一个类,当包含的文法规则很多时,类的个数将急剧增加,导致系统难以管理与维护。
3.可应用的场景比较少。在软件开发中,需要定义语言文法的应用实例非常少,所以这种模式很少被使用到。

<<上一篇:备忘录模式

设计模式篇到此告一段落。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
解释器模式(Interpreter Pattern)是一种行为设计模式,它定义了一种语言文法的表示,并定义了一个解释器,用于解释语言中的句子。它将一个问题分成两个部分:一部分是语言的文法规则,另一部分是解释器,用来解释规则中的句子。解释器模式可以用于处理一些简单的语言,如数学表达式、正则表达式等。 实现方式: 1. 定义抽象表达式类(AbstractExpression),它是所有表达式类的父类,声明了抽象的解释方法。 2. 定义终结符表达式类(TerminalExpression),它实现了抽象表达式类中的解释方法,用于解释语言中的终结符。 3. 定义非终结符表达式类(NonterminalExpression),它也实现了抽象表达式类中的解释方法,用于解释语言中的非终结符。 4. 定义上下文类(Context),它包含了解释器需要的一些全局信息。 5. 客户端使用时,先创建一个上下文对象,然后将需要解释的语言句子作为参数传入解释器对象中,解释器对象将句子解释成相应的结果。 优点: 1. 可扩展性好,增加新的文法规则只需要添加相应的非终结符表达式类即可。 2. 易于实现语法分析。 缺点: 1. 对于复杂的文法规则,解释器模式的类数量可能会很大,增加程序的复杂性。 2. 执行效率较低,因为需要递归调用解释器对象。 适用场景: 1. 可以用于处理一些简单的语言,如数学表达式、正则表达式等。 2. 当语言的文法规则比较复杂时,可以使用解释器模式进行语法分析。 3. 当需要对语言进行增强时,可以使用解释器模式添加新的文法规则。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值