重学设计模式(三设计模式-解释器模式)

Posted 穆瑾轩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重学设计模式(三设计模式-解释器模式)相关的知识,希望对你有一定的参考价值。

1、解释器模式

    解释器模式其实就是按照一定的语法去解析的一些方案,可能我们自己去写这样一些解析规则比较少,但是我们平时可能还用的不少。比如,我们使用的正则表达式、EL表达式、数学表达式等等都是解释器的应用。

1.1、什么是解释器模式

  • 定义

    解释器模式是一种行为设计模式,指给定一种语言,定义其语法的表示形式,以及使用该表示形式来解释该语言中句子

    解释器模式的结构:

    1)抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret();

    2)终结符表达式(Terminal Expression)角色:实现和语法中末端符号相关的 interpret 方法,语法中的每一个终结符都有一个具体终结表达式与之相对应;

    3)非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现语法中与非终结符相关的操作,语法中的每条规则都对应于一个非终结符表达式;

    4)环境(Context)角色:用于存储解释器之外的一些全局信息,通常它临时存储需要解释的语句。

   解释器模式的意图在于:让你根据实现定义好的一些语法规则,组合成和执行的对象。

1.2、解释器模式的优缺点

  • 优点

    扩展性好,在解释器模式中使用类来表示语言的语法规则,因此可以通过继承等机制来改变或扩展语法;

  • 缺点

    1)会引起类膨胀,每条规则至少需要定义一个类,当包含的语法规则很多时,类的个数也会很多,导致系统难以管理与维护;

    2)执行效率问题低,可能在解析规则时使用了大量的循环和递归,效率是一个不容忽视的问题。

1.3、创建方式

    以中文的数学加减乘除法转阿拉伯数字的加减乘除法为例。

1)环境(Context)角色

//环境类
public class Context 

    Map<String,Integer> dict = new HashMap<String,Integer>();
	
    private String exp;
    
	public Context(String exp)
		this.exp = exp;
		dict.put("一", 1);
		dict.put("二", 2);
		dict.put("三", 3);
		dict.put("四", 4);
		dict.put("五", 5);
		dict.put("六", 6);
		dict.put("七", 7);
		dict.put("八", 8);
		dict.put("九", 9);
	

	public Map<String, Integer> getDict() 
		return dict;
	

	public String getExp() 
		return exp;
	

	public void setExp(String exp) 
		this.exp = exp;
	

2)抽象表达式(Abstract Expression)角色

//抽象表达式类
public abstract class AbstractExpression 
	
	public abstract void interpret(Context context);
	

3)终结符表达式(Terminal Expression)角色

public class TerminalExpression extends AbstractExpression

	@Override
	public void interpret(Context context) 
		if(context!=null && !"".equals(context.getExp()))
			String exp = context.getExp();
			for (String str : context.getDict().keySet()) 
				if(exp.contains(str))
					Integer s = context.getDict().get(str);
					exp = exp.replace(str, s+"");
				
			
			context.setExp(exp);
		
	

4)非终结符表达式(Nonterminal Expression)角色

public class NonterminalExpression extends AbstractExpression

	@Override
	public void interpret(Context context) 
		String exp = context.getExp();
		if (exp.contains("加"))
        
            exp= exp.replace("加","+");
        
        if (exp.contains("减"))
        
            exp= exp.replace("减", "-");
        
        if (exp.contains("乘"))
        
            exp= exp.replace("乘", "*");
        
        if (exp.contains("除"))
        
            exp= exp.replace("除", "/");
        
        context.setExp(exp);
	

5)客户端

public class Client 

	public static void main(String[] args) 
		Context context = new Context("一加二加三减二乘三除三");
		AbstractExpression abstractExpression = new TerminalExpression();
		abstractExpression.interpret(context);
		AbstractExpression noabstractExpression = new NonterminalExpression();
        noabstractExpression.interpret(context);
        System.out.println(context.getExp());
	

//输出结果:1+2+3-2*3/3

1.4、总结及建议

    在软件构建过程中,如果某一特定领域的问题比较复杂且类似的情况不断的重复出现,但是使用普通的编程方式来实现可能非常繁琐且不是那么灵活,面临非常频繁的修改,这种情况下使用解释器模式可能会是一种更好的选择。

    其实,以前在开发中也用过这种模式去处理打印数据,将一些打印数据的转换、截取、换行写在配置文件中,用一串规则写在配置文件中作为一种通用的处理(只不过没有按解释器模式这种套路去写的那么规范),实在是处理不了的,才会去单独在代码中重写打印方法去处理打印数据,所以在写代码时设计模式并不是要完全套用的。

应用场景:

    当一个语言需要解释执行时,并且你可以将该语言中的句子表达为一个抽象的语法树时,可以使用解释器模式。

JDK中解释器模式的应用:

    java.util.regex.Pattern

以上是关于重学设计模式(三设计模式-解释器模式)的主要内容,如果未能解决你的问题,请参考以下文章

重学设计模式(三设计模式-原型模式)

重学设计模式(三设计模式-桥接模式)

重学设计模式(三设计模式-备忘录模式)

重学设计模式(三设计模式-备忘录模式)

重学设计模式(三设计模式-代理模式)

重学设计模式(三设计模式-装饰器模式)