赞
踩
解释器模式其实就是按照一定的语法去解析的一些方案,可能我们自己去写这样一些解析规则比较少,但是我们平时可能还用的不少。比如,我们使用的正则表达式、EL表达式、数学表达式等等都是解释器的应用。
定义
解释器模式是一种行为设计模式,指给定一种语言,定义其语法的表示形式,以及使用该表示形式来解释该语言中句子。
解释器模式的结构:
1)抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret();
2)终结符表达式(Terminal Expression)角色:实现和语法中末端符号相关的 interpret 方法,语法中的每一个终结符都有一个具体终结表达式与之相对应;
3)非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现语法中与非终结符相关的操作,语法中的每条规则都对应于一个非终结符表达式;
4)环境(Context)角色:用于存储解释器之外的一些全局信息,通常它临时存储需要解释的语句。
解释器模式的意图在于:让你根据实现定义好的一些语法规则,组合成和执行的对象。
优点
扩展性好,在解释器模式中使用类来表示语言的语法规则,因此可以通过继承等机制来改变或扩展语法;
缺点
1)会引起类膨胀,每条规则至少需要定义一个类,当包含的语法规则很多时,类的个数也会很多,导致系统难以管理与维护;
2)执行效率问题低,可能在解析规则时使用了大量的循环和递归,效率是一个不容忽视的问题。
以中文的数学加减乘除法转阿拉伯数字的加减乘除法为例。
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
在软件构建过程中,如果某一特定领域的问题比较复杂且类似的情况不断的重复出现,但是使用普通的编程方式来实现可能非常繁琐且不是那么灵活,面临非常频繁的修改,这种情况下使用解释器模式可能会是一种更好的选择。
其实,以前在开发中也用过这种模式去处理打印数据,将一些打印数据的转换、截取、换行写在配置文件中,用一串规则写在配置文件中作为一种通用的处理(只不过没有按解释器模式这种套路去写的那么规范),实在是处理不了的,才会去单独在代码中重写打印方法去处理打印数据,所以在写代码时设计模式并不是要完全套用的。
应用场景:
当一个语言需要解释执行时,并且你可以将该语言中的句子表达为一个抽象的语法树时,可以使用解释器模式。
JDK中解释器模式的应用:
java.util.regex.Pattern
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。