• 详解设计模式:解释器模式


    解释器模式(interpreter pattern),是在 GoF 23 种设计模式中定义了的行为型模式。

    解释器模式 这种模式被用在 SQL 解析、符号处理引擎等。

    解释器模式 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。

    本篇文章内容包括:关于解释器模式、解释器模式 Demo(伪代码)



    一、关于解释器模式

    1、关于解释器模式

    解释器模式(interpreter pattern),是在 GoF 23 种设计模式中定义了的行为型模式。

    解释器模式 这种模式被用在 SQL 解析、符号处理引擎等。

    解释器模式 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。

    2、关于解释器模式的构成

    解释器模式包含以下主要 5 种角色。

    • 抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
    • 终结符表达式(Terminal Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
    • 非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
    • 环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
    3、关于解释其模式的UML

    image-20221204212444708

    4、关于访问者模式的适用场景

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

    在 Jdk 中的正则表达式中的 Pattern 类和 Spring 里面的 ExpressionParse 接口使用的是解释器模式的思想。

    当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候,如 XML 文档解释,整体来说还是一种应用较少的设计模式。

    5、关于访问者模式的优缺点

    # 访问者模式优点

    • 访问者模式增加新的操作很容易,只需要增加一个新的访问者即可;
    • 相关的行为,封装到一个访问者中;

    # 访问者模式缺点

    • 增加新数据结构比较困难;
    • 元素变更比较困难,如为被访问的对象增加/减少一些属性,相应的访问者也需要进行修改。

    二、解释器模式 Demo(伪代码)

    1、伪代码 Demo 实现

    # AbstractExpression 抽象表达式(Abstract Expression)角色

    public abstract class AbstractExpression {
    
        /**
         * 解释方法
         * @param info String
         * @return boolean
         */
        public abstract boolean interpret(String info);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    public class NonTerminalExpression extends AbstractExpression {
    
        private AbstractExpression address = null;
        private AbstractExpression name = null;
        private AbstractExpression id = null;
    
        public NonTerminalExpression(AbstractExpression address, AbstractExpression name, AbstractExpression id) {
            this.address = address;
            this.name = name;
            this.id = id;
        }
    
        @Override
        public boolean interpret(String info) {
            String[] strings = info.split("-");
            return address.interpret(strings[0]) && name.interpret(strings[1]) && id.interpret(strings[2]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

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

    import java.util.HashSet;
    import java.util.Set;
    
    public class TerminalExpression extends AbstractExpression {
    
        private final Set<String> set = new HashSet<String>();
    
        public TerminalExpression(String[] data) {
            for (int i = 0; i < data.length; i++)
                set.add(data[i]);
        }
    
    
        @Override
        public boolean interpret(String info) {
            if (set.contains(info)) {
                return true;
            }
            return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    # Context 环境(Context)角色

    public class Context {
    
        private final AbstractExpression information;
    
        public Context() {
            String[] number1 = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
            AbstractExpression number = new TerminalExpression(number1);
            String[] xxZm1 = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"};
            AbstractExpression xxZm = new TerminalExpression(xxZm1);
            String[] dxZm1 = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"};
            AbstractExpression dxZm = new TerminalExpression(dxZm1);
            information = new NonTerminalExpression(number, xxZm, dxZm);
        }
    
        public void interpreter(String info) {
            boolean ok = information.interpret(info);
            if (ok) {
                System.out.println("正确! [" + info + "] 满足  [单个数字-单个小写-单个大写]  的条件");
            } else {
                System.out.println("错误! [" + info + "] 不满足  [单个数字-单个小写-单个大写]  的条件");
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    2、Demo 测试
    public class Client {
        
        public static void main(String[] args) {
            Context people = new Context();
            people.interpreter("2-a-A");
            people.interpreter("11-A-5");
            people.interpreter("你-好-吖");
            people.interpreter("2aA");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    接口与抽象类的相同与不同
    别说你不会网络请求了,6000字入门Axios框架
    Android之AMessage机制存/取原理(四十四)
    Python100天学习打卡第一天环境配置
    码神之路项目总结(四)
    Java面向对象基础 笔记记录
    提升前端性能的 JavaScript 技巧
    460. LFU 缓存
    部署Harbor镜像仓库
    Spring - ApplicationContextInitializer 扩展接口
  • 原文地址:https://blog.csdn.net/weixin_45187434/article/details/128213942