当前位置:   article > 正文

重学设计模式(三、设计模式-解释器模式)_解释器模式意图

解释器模式意图

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)角色

  1. //环境类
  2. public class Context {
  3. Map<String,Integer> dict = new HashMap<String,Integer>();
  4. private String exp;
  5. public Context(String exp){
  6. this.exp = exp;
  7. dict.put("一", 1);
  8. dict.put("二", 2);
  9. dict.put("三", 3);
  10. dict.put("四", 4);
  11. dict.put("五", 5);
  12. dict.put("六", 6);
  13. dict.put("七", 7);
  14. dict.put("八", 8);
  15. dict.put("九", 9);
  16. }
  17. public Map<String, Integer> getDict() {
  18. return dict;
  19. }
  20. public String getExp() {
  21. return exp;
  22. }
  23. public void setExp(String exp) {
  24. this.exp = exp;
  25. }
  26. }

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

  1. //抽象表达式类
  2. public abstract class AbstractExpression {
  3. public abstract void interpret(Context context);
  4. }

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

  1. public class TerminalExpression extends AbstractExpression{
  2. @Override
  3. public void interpret(Context context) {
  4. if(context!=null && !"".equals(context.getExp())){
  5. String exp = context.getExp();
  6. for (String str : context.getDict().keySet()) {
  7. if(exp.contains(str)){
  8. Integer s = context.getDict().get(str);
  9. exp = exp.replace(str, s+"");
  10. }
  11. }
  12. context.setExp(exp);
  13. }
  14. }
  15. }

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

  1. public class NonterminalExpression extends AbstractExpression{
  2. @Override
  3. public void interpret(Context context) {
  4. String exp = context.getExp();
  5. if (exp.contains("加"))
  6. {
  7. exp= exp.replace("加","+");
  8. }
  9. if (exp.contains("减"))
  10. {
  11. exp= exp.replace("减", "-");
  12. }
  13. if (exp.contains("乘"))
  14. {
  15. exp= exp.replace("乘", "*");
  16. }
  17. if (exp.contains("除"))
  18. {
  19. exp= exp.replace("除", "/");
  20. }
  21. context.setExp(exp);
  22. }
  23. }

5)客户端

  1. public class Client {
  2. public static void main(String[] args) {
  3. Context context = new Context("一加二加三减二乘三除三");
  4. AbstractExpression abstractExpression = new TerminalExpression();
  5. abstractExpression.interpret(context);
  6. AbstractExpression noabstractExpression = new NonterminalExpression();
  7. noabstractExpression.interpret(context);
  8. System.out.println(context.getExp());
  9. }
  10. }
  11. //输出结果:1+2+3-2*3/3

1.4、总结及建议

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

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

应用场景:

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

JDK中解释器模式的应用:

    java.util.regex.Pattern

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/733808
推荐阅读
相关标签
  

闽ICP备14008679号