【再谈设计模式】解释器模式~语法的解析执行者

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
简介: 解释器模式定义了一种语言的语法表示,并定义一个解释器来解释该语言中的句子。它使用类来表示每个语法规则,并且通过递归调用这些类的方法来解释表达式。本质上,它将一个复杂的表达式分解为一系列简单的部分,然后按照特定的语法规则进行解析和执行。

{6D7EEA4A-8EF8-477D-82E1-5765920178B5}.png


一、引言

       在软件工程,软件开发领域,设计模式是解决常见问题的可复用方案。解释器模式是一种行为型设计模式,它为语言创建解释器,就像编译器或解释器处理高级编程语言一样。这种模式在处理特定领域语言(DSL)或者需要解析和执行特定语法规则的场景下非常有用。通过理解解释器模式,我们可以更好地处理复杂的语法结构,将其转化为可执行的代码逻辑。

二、定义与描述

       解释器模式定义了一种语言的语法表示,并定义一个解释器来解释该语言中的句子。它使用类来表示每个语法规则,并且通过递归调用这些类的方法来解释表达式。本质上,它将一个复杂的表达式分解为一系列简单的部分,然后按照特定的语法规则进行解析和执行。

{775BEBB4-43CA-4E90-B9CD-51F2B1675641}.png

三、抽象背景

       在许多应用场景中,我们需要处理一些自定义的、具有特定语法规则的语言。例如,在数据库查询语言中,有特定的语法来表示查询条件(如SQL语句);在数学表达式求值中,有运算符号和数字组成的表达式(如3 + 4 * 2)。解释器模式提供了一种方式,将这些表达式转化为可执行的操作。

四、适用场景与现实问题解决

特定领域语言(DSL)处理

       现实问题:在配置文件中,可能存在一种自定义的配置语言,用于描述系统的某些行为。例如,在游戏开发中,可能有自定义的脚本语言来控制游戏角色的行为。

       解决方案:使用解释器模式可以编写解释器来解析这些自定义的脚本语言,从而实现游戏角色按照脚本中的指令进行行动。

{C6DF705D-31D5-47C5-BA38-A57CACFE6449}.png

数学表达式求值

       现实问题:在科学计算或者金融计算中,需要对包含变量和运算符的数学表达式进行求值。

       解决方案:解释器模式可以将数学表达式分解为数字、变量和运算符等元素,然后按照数学运算规则进行求值。

{9291F5B8-70BC-4230-BCFC-47A9EE4112AD}.png

五、解释器模式的现实生活的例子

音乐乐谱解释

       初衷:音乐乐谱是一种特定的“语言”,它由音符、节拍、休止符等元素按照一定的规则组成。音乐家需要将乐谱上的符号转化为实际的音乐演奏。

       问题解决:可以将乐谱看作是一种待解释的表达式,使用解释器模式创建一个解释器,将乐谱中的每个元素(音符等)解释为对应的音乐演奏指令,如音高、持续时间等,从而实现音乐的演奏。

{836FD602-3586-473E-BB1D-06526B580170}.png

六、代码示例

Java代码示例

// 抽象表达式
interface Expression {    int interpret();
}
// 终结符表达式 - 数字
class NumberExpression implements Expression {  
    private int number;    public NumberExpression(int number) {    
        this.number = number;
    }  
    @Override
    public int interpret() {   
        return number;
    }
}
// 非终结符表达式 - 加法
class AddExpression implements Expression {  
    private Expression left;   
    private Expression right;  
    public AddExpression(Expression left, Expression right) {   
        this.left = left;        
        this.right = right;
    }   
    @Override
    public int interpret() {       
        return left.interpret() + right.interpret();
    }
}
public class InterpreterPatternJava {  
    public static void main(String[] args) {     
        Expression num1 = new NumberExpression(3);  
        Expression num2 = new NumberExpression(4);  
        Expression add = new AddExpression(num1, num2);
        System.out.println("结果: " + add.interpret());
    }
}


类图:

{66F8D60F-2696-41E6-ADC4-265562AA4D32}.png

流程图:

{0C599FED-AFE8-4121-9492-4FBEFC26FD5F}.png

时序图:

{A2F02221-742F-4A93-A813-9653472E6CFB}.png


C++代码示例

#include 
// 抽象表达式类
class Expression {
    public:    virtual int interpret() = 0;
};
// 数字表达式类(终结符表达式)
class NumberExpression : public Expression {
    private:    int number;
    public:    NumberExpression(int num) : number(num) {}   
    int interpret() override {   
        return number;
    }
};
// 加法表达式类(非终结符表达式)
class AddExpression : public Expression {
    private:
    Expression* left;
    Expression* right;public:   
    AddExpression(Expression* l, Expression* r) : left(l), right(r) {}    
    int interpret() override {       
        return left->interpret() + right->interpret();
    }
};
int main() {
    Expression* num1 = new NumberExpression(3);
    Expression* num2 = new NumberExpression(4);
    Expression* add = new AddExpression(num1, num2);
    std::cout << "结果: " << add->interpret() << std::endl;    return 0;
}

Python代码示例

# 抽象表达式
class Expression:   
    def interpret(self):      
        pass
    # 终结符表达式 - 数字
    class NumberExpression(Expression):   
        def __init__(self, number):
        self.number = number   
        def interpret(self):      
            return self.number
        # 非终结符表达式 - 加法
        class AddExpression(Expression):  
            def __init__(self, left, right):
        self.left = left
        self.right = right   
        def interpret(self):    
            return self.left.interpret() + self.right.interpret()
num1 = NumberExpression(3)
num2 = NumberExpression(4)
add = AddExpression(num1, num2)print("结果:", add.interpret())

Go代码示例

// 抽象表达式接口
type Expression interface {
    interpret() int}
// 数字表达式结构体(终结符表达式)
type NumberExpression struct {
    number int}func (n *NumberExpression) interpret() int {   
    return n.number
}
// 加法表达式结构体(非终结符表达式)
type AddExpression struct {
    left  Expression
    right Expression
}
func (a *AddExpression) interpret() int { 
    return a.left.interpret() + a.right.interpret()
}
func main() {
    num1 := &NumberExpression{3}
    num2 := &NumberExpression{4}
    add := &AddExpression{num1, num2}    println("结果:", add.interpret())
}

七、解释器模式的优缺点

优点

灵活性

       可以很容易地改变和扩展语法规则,只要修改相应的表达式类即可。

可维护性

       每个语法规则都由一个单独的类表示,使得代码结构清晰,易于理解和维护。

易于实现简单的语法

       对于简单的语法规则,解释器模式可以快速实现解析和执行功能。

缺点

复杂性

       对于复杂的语法,可能需要创建大量的表达式类,导致类的数量过多,增加系统的复杂性。

性能问题

       解释器模式通常是通过递归调用方法来解释表达式,对于复杂的表达式可能会导致性能下降。

{098206DC-B79D-4C56-B3E9-2EE210D56714}.png

八、解释器模式的升级版

语法分析器生成器(Parser Generator)

       一些工具如ANTLR(Another Tool for Language Recognition)可以根据语法定义自动生成语法分析器。这种方式比手动编写解释器模式更加高效和准确,尤其适用于复杂的语法结构。它将语法定义与代码实现分离,使得语法的修改更加方便,同时可以生成更加优化的解析代码,提高性能。

{0F1FD572-521E-4A93-94D6-CED061341EBB}.png

目录
相关文章
|
4月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
4月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
4月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
4月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
4月前
|
设计模式 Java 程序员
【23种设计模式·全精解析 | 概述篇】设计模式概述、UML图、软件设计原则
本系列文章聚焦于面向对象软件设计中的设计模式,旨在帮助开发人员掌握23种经典设计模式及其应用。内容分为三大部分:第一部分介绍设计模式的概念、UML图和软件设计原则;第二部分详细讲解创建型、结构型和行为型模式,并配以代码示例;第三部分通过自定义Spring的IOC功能综合案例,展示如何将常用设计模式应用于实际项目中。通过学习这些内容,读者可以提升编程能力,提高代码的可维护性和复用性。
【23种设计模式·全精解析 | 概述篇】设计模式概述、UML图、软件设计原则
|
6月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入解析与实践
【10月更文挑战第12天】 在软件开发的世界中,设计模式是解决常见问题的最佳实践。它们不是具体的代码,而是一种编码和设计经验的总结。在PHP开发中,合理运用设计模式可以极大地提高代码的可维护性、扩展性和复用性。本文将深入探讨策略模式(Strategy Pattern)的原理、实现方式及其在PHP中的应用。通过具体示例,我们将展示如何利用策略模式来解耦算法与对象,从而让代码更加灵活和易于管理。
51 0
|
6月前
|
设计模式 存储 安全
PHP中的设计模式:单例模式的深入解析与实践
在PHP开发中,设计模式是提高代码可维护性、扩展性和重用性的关键技术之一。本文将深入探讨单例模式(Singleton Pattern)的原理、实现方式及其在PHP中的应用,同时通过实例展示如何在具体的项目场景中有效利用单例模式来管理和组织对象,确保全局唯一性的实现和最佳实践。
|
1月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
173 29
|
5月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
168 2
|
1月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
60 3

热门文章

最新文章

推荐镜像

更多
下一篇
oss创建bucket