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