【第23节】C++设计模式(行为模式)-Interpreter(解释器)模式

一、问题背景

        在一些应用中,系统会提供内建(Build-In)的脚本或宏语言,允许用户定义他们能够在系统中执行的操作。Interpreter 模式的目的就是为用户提供一种定义语言的语法表示,并通过解释器来解释语言中的句子。这种模式的核心思想是将语言的语法规则表示为类,并通过这些类来解析和执行用户输入的语句。

        Interpreter 模式为构建语法解释器提供了一个框架。例如,开发了一个编译系统 ,该系统可以使用 Interpreter 模式来实现语法解析功能。Interpreter 模式不仅适用于编译器设计,还可以用于解析配置文件、查询语言、规则引擎等场景。

 

二、模式选择

Interpreter 模式的典型结构图如下:

在 Interpreter 模式中,主要包含以下几个角色:

(1)AbstractExpression(抽象表达式):定义解释器的接口,包含一个 `Interpret` 方法。
(2)TerminalExpression(终结符表达式):实现与文法中的终结符相关的解释操作。
(3)NonterminalExpression(非终结符表达式):实现与文法中的非终结符相关的解释操作,通常包含对其他表达式的引用。
(4)Context(上下文):包含解释器需要的全局信息。

通过这种设计,Interpreter 模式将语法规则表示为类的层次结构,从而实现对语句的解释。

 

三、代码实现

        下面我们将通过一个完整的 C++ 代码示例来展示如何实现 Interpreter 模式。

代码片段 1:Context.h

// Context.h
#ifndef _CONTEXT_H_
#define _CONTEXT_H_

// Context 类:为解释过程提供全局信息
class Context {
public:
    Context();
    ~Context();
protected:
private:
};

#endif //~_CONTEXT_H_

代码片段 2:Context.cpp

// Context.cpp
#include "Context.h"

// Context 类的实现
Context::Context() {
    // 构造函数
}

Context::~Context() {
    // 析构函数
}

代码片段 3:Interpret.h

// Interpret.h
#ifndef _INTERPRET_H_
#define _INTERPRET_H_

#include "Context.h"
#include <string>
using namespace std;

// AbstractExpression 类:定义解释器的接口
class AbstractExpression {
public:
    virtual ~AbstractExpression();
    virtual void Interpret(const Context& c) = 0;  // 解释方法
protected:
    AbstractExpression();
private:
};

// TerminalExpression 类:终结符表达式
class TerminalExpression : public AbstractExpression {
public:
    TerminalExpression(const string& statement);  // 构造函数
    ~TerminalExpression();
    void Interpret(const Context& c);  // 实现解释方法
protected:
private:
    string _statement;  // 终结符内容
};

// NonterminalExpression 类:非终结符表达式
class NonterminalExpression : public AbstractExpression {
public:
    NonterminalExpression(AbstractExpression* expression, int times);  // 构造函数
    ~NonterminalExpression();
    void Interpret(const Context& c);  // 实现解释方法
protected:
private:
    AbstractExpression* _expression;  // 子表达式
    int _times;  // 重复次数
};

#endif //~_INTERPRET_H_

代码片段 4:Interpret.cpp

// Interpret.cpp
#include "Interpret.h"
#include <iostream>
using namespace std;

// AbstractExpression 类的实现
AbstractExpression::AbstractExpression() {
    // 构造函数
}

AbstractExpression::~AbstractExpression() {
    // 析构函数
}

void AbstractExpression::Interpret(const Context& c) {
    // 默认实现为空
}

// TerminalExpression 类的实现
TerminalExpression::TerminalExpression(const string& statement) {
    this->_statement = statement;  // 初始化终结符内容
}

TerminalExpression::~TerminalExpression() {
    // 析构函数
}

void TerminalExpression::Interpret(const Context& c) {
    // 解释终结符
    cout << this->_statement << " TerminalExpression" << endl;
}

// NonterminalExpression 类的实现
NonterminalExpression::NonterminalExpression(AbstractExpression* expression, int times) {
    this->_expression = expression;  // 初始化子表达式
    this->_times = times;  // 初始化重复次数
}

NonterminalExpression::~NonterminalExpression() {
    // 析构函数
}

void NonterminalExpression::Interpret(const Context& c) {
    // 解释非终结符
    for (int i = 0; i < _times; i++) {
        this->_expression->Interpret(c);  // 重复解释子表达式
    }
}

代码片段 5:main.cpp

// main.cpp
#include "Context.h"
#include "Interpret.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[]) {
    // 创建上下文对象
    Context* c = new Context();

    // 创建终结符表达式
    AbstractExpression* te = new TerminalExpression("hello");

    // 创建非终结符表达式
    AbstractExpression* nte = new NonterminalExpression(te, 2);

    // 解释非终结符表达式
    nte->Interpret(*c);

    // 释放内存
    delete nte;
    delete te;
    delete c;

    return 0;
}

代码说明

(1)Context 类:为解释过程提供全局信息。在实际应用中,可以扩展此类以存储解释器需要的额外数据。
(2)AbstractExpression 类:定义解释器的接口,所有具体表达式类都需要实现 `Interpret` 方法。
(3)TerminalExpression 类:实现与终结符相关的解释操作。例如,在解析算术表达式时,终结符可以是数字或变量。
(4)NonterminalExpression 类:实现与非终结符相关的解释操作。例如,在解析算术表达式时,非终结符可以是加法或乘法操作。

 

四、总结讨论

Interpreter 模式在以下场景中非常有用:

(1)解析配置文件:例如 XML、JSON 等格式的配置文件。
(2)查询语言:例如 SQL 查询解析器。
(3)规则引擎:例如业务规则的解释和执行。

在实际开发中,Interpreter 模式可以与其他设计模式结合使用。例如:
(1)使用 **Flyweight 模式** 共享终结符对象,减少内存占用。
(2)使用 **Composite 模式** 构建复杂的语法树。

        Interpreter 模式通过将语法规则表示为类的层次结构,提供了一种灵活的方式来解释语言中的句子。这种模式不仅适用于编译器设计,还可以用于解析配置文件、查询语言、规则引擎等场景。通过 Interpreter 模式,我们可以将复杂的语法解析逻辑分解为简单的类,从而提高代码的可维护性和可扩展性。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/984142.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

哈弗赛恩公式计算长度JavaScript实现

哈弗赛恩公式&#xff08;Haversine formula&#xff09;是一种用于计算球面上两点间最短距离的数学方法&#xff0c;尤其适用于地球表面。本文将详细介绍哈弗赛恩公式的原理、应用以及如何使用JavaScript实现它。 一、哈弗赛恩公式原理 在球面几何中&#xff0c;哈弗赛恩公式…

Day05 实例:正向反向连接内外网环境防火墙出入站

一、正反向连接 0、先将防火墙关闭 Linux&#xff1a; sudo systemctl stop firewalld Windows&#xff1a;netsh advfirewall set allprofiles state off 1、正向连接 1.1 Linux连接Windows 00x1 开启两台服务器 并且给Windows拖入nc.exe 00x2 Windows绑定自己5566端…

【大模型知识点】位置编码——绝对位置编码,相对位置编码,旋转位置编码RoPE

由于Transformer 中的自注意模块具有置换不变性&#xff08;不关心输入序列的顺序&#xff09;&#xff0c;因此需要使用位置编码来注入位置信息以建模序列&#xff0c;使模型能够区分不同位置的 token&#xff0c;并捕捉序列的顺序关系。 在介绍一些位置编码方法前&#xff0…

Linux 配置静态 IP

一、简介 在 Linux CentOS 系统中默认动态分配 IP 地址&#xff0c;每次启动虚拟机服务都是不一样的 IP&#xff0c;因此要配置静态 IP 地址避免每次都发生变化&#xff0c;下面将介绍配置静态 IP 的详细步骤。 首先先理解一下动态 IP 和静态 IP 的概念&#xff1a; 动态 IP…

DeepSeek 3FS:端到端无缓存的存储新范式

在 2025 年 2 月 28 日&#xff0c;DeepSeek 正式开源了其高性能分布式文件系统 3FS【1】&#xff0c;作为其开源周的压轴项目&#xff0c;3FS 一经发布便引发了技术圈的热烈讨论。它不仅继承了分布式存储的经典设计&#xff0c;还通过极简却高效的架构&#xff0c;展现了存储技…

微服务与消息队列RabbitMQ

简介 同步模式 异步模式 内容 解决方案RabbitMQ 同步调用的优缺点 同步调用的优势是什么&#xff1f; 时效性强&#xff0c;等待到结果后才返回。 同步调用的问题是什么&#xff1f; 拓展性差性能下降级联失败问题

vue+element-plus简洁完美实现古诗文网

目录 一、项目介绍 二、项目截图 1.项目结构图 2.首页&#xff08;推荐&#xff09; 3.诗文 4.名句 5.作者 6.古籍 7.我的 三、源码实现 1.路由配置 2.顶部 四、总结 一、项目介绍 项目在线预览&#xff1a;点击访问 本项目为vue项目&#xff0c;参考古诗文网官方…

Vue项目通过内嵌iframe访问另一个vue页面,获取token适配后端鉴权(以内嵌若依项目举例)

1. 改造子Vue项目进行适配(ruoyi举例) (1) 在路由文件添加需要被外链的vue页面配置 // 若依项目的话是 router/index.js文件 {path: /contrast,component: () > import(/views/contrast/index),hidden: true },(2) 开放白名单 // 若依项目的话是 permission.js 文件 cons…

RuleOS:区块链开发的“破局者”,开启Web3新纪元

RuleOS&#xff1a;区块链开发的“破冰船”&#xff0c;驶向Web3的星辰大海 在区块链技术的浩瀚宇宙中&#xff0c;一群勇敢的探索者正驾驶着一艘名为RuleOS的“破冰船”&#xff0c;冲破传统开发的冰层&#xff0c;驶向Web3的星辰大海。这艘船&#xff0c;正以一种前所未有的姿…

指针的工作原理,函数的传值和传址

在C之中&#xff0c;指针是一个变量用于存储另外一个变量的内存地址。指针可以指向各种数据类型例如基础数据类型和自定义数据类型等。 在计算机之中的内存被划分为一个一个的存储单元&#xff0c;每个存储单元拥有唯一的内存地址&#xff0c;指针就是指向这些内存单元的地址。…

RISC-V汇编学习(三)—— RV指令集

有了前两节对于RISC-V汇编、寄存器、汇编语法等的认识&#xff0c;本节开始介绍RISC-V指令集和伪指令。 前面说了RISC-V的模块化特点&#xff0c;是以RV32I为作为ISA的核心模块&#xff0c;其他都是要基于此为基础&#xff0c;可以这样认为&#xff1a;RISC-V ISA 基本整数指…

基于控制障碍函数(Control Barrier Function)的二次规划(QP)控制

文章目录 研究背景主要贡献障碍函数&#xff08;Barrier Function&#xff09;&#xff08;一&#xff09;倒数障碍函数&#xff08;Reciprocal Barrier Function, RBF&#xff09;&#xff08;二&#xff09;归零障碍函数&#xff08;Zeroing Barrier Function, ZBF&#xff0…

软件工程:软件需求之需求分析方法

目录 前言 需求分析方法 工具和方法 具体分析方法 对运行环境的影响 ​编辑 前言 本文重点介绍开展软件需求分析的方法。 需求分析方法 工具和方法 软件需求可以维护在ALM系统中&#xff0c;譬如&#xff1a;doors&#xff0c;codeBeamer等&#xff0c;JIRA适合互联网行…

蓝桥杯—走迷宫(BFS算法)

题目描述 给定一个NM 的网格迷宫 G。G 的每个格子要么是道路&#xff0c;要么是障碍物&#xff08;道路用 11表示&#xff0c;障碍物用 0 表示&#xff09;。 已知迷宫的入口位置为 (x1​,y1​)&#xff0c;出口位置为 (x2​,y2​)。问从入口走到出口&#xff0c;最少要走多少…

Ubuntu无风扇工控机:解决精密仪器散热难题的利器

在现代工业自动化领域&#xff0c;精密仪器的控制对设备的稳定性、可靠性和静音性提出了极高的要求。而无风扇Ubuntu工控机&#xff0c;凭借其独特的无风扇设计和强大的计算能力&#xff0c;正逐渐成为精密仪器控制场景中的“无声守护者”。本文将深入探讨无风扇工控机在精密仪…

TCP协议与包头格式

patience is key in life&#xff01;&#xff01;&#xff01; 文章目录 一、什么是TCP&#xff1f;二、TCP的特点三、TCP为什么可靠&#xff1f;四、TCP的包头格式五、TCP的三次握手与四次挥手1.三次握手2.四次挥手 一、什么是TCP&#xff1f; TCP&#xff08;Transmission …

LeetCode Hot100刷题——反转链表(迭代+递归)

206.反转链表 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示例 3&#…

【Linux】http 协议

目录 一、http协议 &#xff08;一&#xff09;http 协议的概念 &#xff08;二&#xff09;URL的组成 &#xff08;三&#xff09;urlencode 和 urldecode 二、http 的协议格式 &#xff08;一&#xff09;http 请求方法 &#xff08;二&#xff09;http 响应状态码 &a…

ACE协议学习1

在多核系统或复杂SoC&#xff08;System on Chip&#xff09;中&#xff0c;不同处理器核心或IP&#xff08;Intellectual Property&#xff09;模块之间需要保持数据的一致性。常用的是ACE协议or CHI。 先对ACE协议进行学习 ACE协议&#xff08;Advanced Microcontroller Bu…

ES-分词器安装与使用详解

安装分词器 windows环境&#xff0c;分词器有2种安装方式&#xff0c;1.直接命令安装&#xff1b;2.压缩包安装 IK分词器 查看ik分词器文档&#xff0c;找到安装方式介绍 文档链接&#xff1a; 方式1 elasticsearch-plugin install https://get.infini.cloud/elasticsearch/an…