当前位置: 首页 > news >正文

C++软件设计模式之状态模式

在C++设计模式中,状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为,使对象看起来似乎修改了其类。状态模式的主要动机、意图和适用场合如下:

动机

在面向对象的设计中,对象的行为往往依赖于其状态。传统的实现方式是在对象中使用大量的条件语句来检查状态并执行相应的操作。这种做法有以下几个问题:

  • 代码复杂性:随着状态的增多,条件语句会变得越来越复杂,难以维护。
  • 可扩展性差:添加新状态时,需要修改现有的条件语句,违反了开闭原则(对扩展开放,对修改关闭)。
  • 状态转移不清晰:状态之间的转移逻辑分散在各个地方,不便于管理和理解。

为了解决这些问题,状态模式应运而生。

意图

状态模式的意图是将对象的状态抽象成类层次结构,并将行为封装在这些状态类中。具体来说:

  • 定义一个状态接口,该接口声明了所有可能状态共有的操作。
  • 为每种状态实现一个具体的类,每个类都实现了状态接口中的操作,并在必要时处理状态转换。
  • 维护一个当前状态的引用,主体对象通过这个引用委托给当前状态对象执行相应的操作。

通过这种方式,状态模式将状态相关的逻辑从主体类中分离出来,使得代码更加清晰、模块化,并且易于扩展。

适用场景

状态模式适用于以下情况:

  1. 对象行为依赖于其状态,且需要根据状态改变行为。
  2. 状态之间有复杂的转移逻辑,需要明确地定义状态转换规则。
  3. 希望将状态相关的代码集中管理,提高代码的可维护性和可扩展性。
  4. 需要对不同的状态进行不同的操作,并且这些操作可能涉及复杂的业务逻辑。

例如,一个自动售货机可以根据其当前状态(如待支付、已支付、缺货等)执行不同的操作,如接收硬币、发放商品、退还余额等。使用状态模式可以清晰地定义每种状态下的行为以及状态之间的转换。

示例代码

以下是一个简单的C++示例,展示了状态模式的使用:

#include <iostream>
#include <memory>// 状态接口
class State {
public:virtual void handle(const std::string& input) = 0;virtual ~State() = default;
};// 具体状态A
class StateA : public State {
public:void handle(const std::string& input) override {std::cout << "StateA handles: " << input << std::endl;// 可能会转换到其他状态}
};// 具体状态B
class StateB : public State {
public:void handle(const std::string& input) override {std::cout << "StateB handles: " << input << std::endl;// 可能会转换到其他状态}
};// 主体类
class Context {
public:void setState(std::shared_ptr<State> state) {currentState = state;}void request(const std::string& input) {if (currentState) {currentState->handle(input);}}
private:std::shared_ptr<State> currentState;
};int main() {// 创建具体状态实例auto stateA = std::make_shared<StateA>();auto stateB = std::make_shared<StateB>();// 创建上下文并设置初始状态Context context;context.setState(stateA);// 处理请求context.request("Initial request");// 转换状态context.setState(stateB);context.request("Another request");return 0;
}

在这个示例中,Context 类维护了一个 State 接口的指针,并将处理请求委托给当前状态对象。不同的状态类 (StateA 和 StateB) 实现了不同的处理逻辑。通过设置不同的状态,Context 对象可以表现出不同的行为。

通过这种方式,状态模式使得状态相关的逻辑更加清晰和模块化,同时也便于添加新的状态而不需要修改现有的代码。

 

面是一个使用状态模式来模拟Windows PnP(Plug and Play)设备驱动中状态转移的C++示例。我们将定义一个设备驱动类和多个状态类,每个状态类将处理不同状态下的设备行为和状态转移。

状态模式在PnP设备驱动中的应用

  1. 定义状态接口:定义一个状态接口 State,声明所有可能状态共有的操作。
  2. 实现具体状态类:为每种状态(如 UnpluggedPlugInInitializeReady)实现一个具体的类。
  3. 维护当前状态:在 DeviceDriver 类中维护一个当前状态的引用,并根据需要切换状态。

示例代码

#include <iostream>
#include <memory>
#include <string>// 状态接口
class State {
public:virtual ~State() = default;virtual void onUnplug(DeviceDriver* driver) = 0;virtual void onPlugIn(DeviceDriver* driver) = 0;virtual void onInitialize(DeviceDriver* driver) = 0;virtual void onReady(DeviceDriver* driver) = 0;
};// 设备驱动类
class DeviceDriver {
public:DeviceDriver() : currentState(std::make_shared<Unplugged>()) {}void unplug() {currentState->onUnplug(this);}void plugIn() {currentState->onPlugIn(this);}void initialize() {currentState->onInitialize(this);}void ready() {currentState->onReady(this);}void setState(const std::shared_ptr<State>& state) {currentState = state;}private:std::shared_ptr<State> currentState;
};// 具体状态:未插入
class Unplugged : public State {
public:void onUnplug(DeviceDriver* driver) override {std::cout << "Already unplugged." << std::endl;}void onPlugIn(DeviceDriver* driver) override {std::cout << "Device plugged in." << std::endl;driver->setState(std::make_shared<PlugIn>());}void onInitialize(DeviceDriver* driver) override {std::cout << "Cannot initialize. Device not plugged in." << std::endl;}void onReady(DeviceDriver* driver) override {std::cout << "Cannot be ready. Device not plugged in." << std::endl;}
};// 具体状态:已插入
class PlugIn : public State {
public:void onUnplug(DeviceDriver* driver) override {std::cout << "Device unplugged." << std::endl;driver->setState(std::make_shared<Unplugged>());}void onPlugIn(DeviceDriver* driver) override {std::cout << "Already plugged in." << std::endl;}void onInitialize(DeviceDriver* driver) override {std::cout << "Device initialized." << std::endl;driver->setState(std::make_shared<Initialize>());}void onReady(DeviceDriver* driver) override {std::cout << "Cannot be ready. Device not initialized." << std::endl;}
};// 具体状态:已初始化
class Initialize : public State {
public:void onUnplug(DeviceDriver* driver) override {std::cout << "Device unplugged." << std::endl;driver->setState(std::make_shared<Unplugged>());}void onPlugIn(DeviceDriver* driver) override {std::cout << "Already plugged in and initialized." << std::endl;}void onInitialize(DeviceDriver* driver) override {std::cout << "Already initialized." << std::endl;}void onReady(DeviceDriver* driver) override {std::cout << "Device is ready to use." << std::endl;driver->setState(std::make_shared<Ready>());}
};// 具体状态:已准备好
class Ready : public State {
public:void onUnplug(DeviceDriver* driver) override {std::cout << "Device unplugged." << std::endl;driver->setState(std::make_shared<Unplugged>());}void onPlugIn(DeviceDriver* driver) override {std::cout << "Device is already ready." << std::endl;}void onInitialize(DeviceDriver* driver) override {std::cout << "Device is already initialized and ready." << std::endl;}void onReady(DeviceDriver* driver) override {std::cout << "Device is already ready." << std::endl;}
};int main() {DeviceDriver driver;// 模拟设备插拔和状态转移driver.plugIn();driver.initialize();driver.ready();driver.unplug();driver.plugIn();driver.ready();return 0;
}

代码说明

  1. 状态接口 State

    • 定义了四个虚函数:onUnplugonPlugInonInitializeonReady,分别对应设备在不同状态下的行为。
  2. 设备驱动类 DeviceDriver

    • 维护一个当前状态 currentState,并提供四个公共方法 unplugplugIninitializeready,这些方法委托给当前状态对象处理。
    • 提供 setState 方法用于切换状态。
  3. 具体状态类

    • Unplugged:设备未插入状态。
    • PlugIn:设备已插入状态。
    • Initialize:设备已初始化状态。
    • Ready:设备已准备好状态。
  4. 主函数 main

    • 创建一个 DeviceDriver 对象,并模拟设备的插拔和状态转移过程。

通过这种方式,状态模式使得设备驱动的代码更加模块化和可维护,状态之间的转换也更加清晰

 

状态模式通常与其他设计模式协同使用,以提高代码的模块化和可维护性。以下是状态模式常见的协同模式及其使用场景:

1. 策略模式 (Strategy Pattern)

  • 场景:当不同状态下的行为可以通过不同的算法实现时,可以使用策略模式来定义这些算法。
  • 协同方式:状态模式中的每个状态类可以包含一个策略对象,用于实现具体的行为。这样,状态的改变不仅涉及状态的切换,还可以动态改变算法。
  • 示例:在状态模式中,不同状态下的设备初始化可以使用不同的初始化策略。

2. 工厂模式 (Factory Pattern)

  • 场景:当状态类的创建需要复杂逻辑时,可以使用工厂模式来创建状态对象。
  • 协同方式:通过工厂模式,可以在状态切换时动态创建所需的状态对象,而不需要在每个地方重复创建逻辑。
  • 示例:使用工厂模式创建设备驱动的初始状态或特定状态。

3. 观察者模式 (Observer Pattern)

  • 场景:当状态变化需要通知其他对象时,可以使用观察者模式。
  • 协同方式:状态对象可以充当被观察者,其他对象(如日志记录器、UI 更新器等)可以注册为观察者,当状态变化时,观察者会收到通知并作出相应处理。
  • 示例:在设备驱动状态变化时,通知UI更新显示状态。

4. 单例模式 (Singleton Pattern)

  • 场景:当状态类需要全局唯一实例时,可以使用单例模式。
  • 协同方式:状态类可以通过单例模式确保每个状态在整个应用中只有一个实例,这有助于节省资源并确保状态的一致性。
  • 示例:确保设备的“未插入”状态在整个应用中只有一个实例。

5. 模板方法模式 (Template Method Pattern)

  • 场景:当状态类有共同的骨架方法,但具体实现不同步时,可以使用模板方法模式。
  • 协同方式:状态类可以定义一个模板方法,该方法包含一系列步骤,其中某些步骤的具体实现由具体的子类提供。
  • 示例:定义一个模板方法 handleEvent,该方法包含一系列步骤,如检查前置条件、执行操作、更新状态等,具体状态类可以覆盖这些步骤的实现。

6. 命令模式 (Command Pattern)

  • 场景:当状态变化需要记录或撤销时,可以使用命令模式。
  • 协同方式:每个状态变化可以封装成一个命令对象,命令对象可以记录状态变化的操作,便于撤回或重做。
  • 示例:记录设备状态变化的命令,以便在需要时恢复到之前的状态。

7. 责任链模式 (Chain of Responsibility Pattern)

  • 场景:当状态变化需要多个对象处理时,可以使用责任链模式。
  • 协同方式:状态变化可以传递给一个链中的多个对象,每个对象根据其职责处理或传递请求。
  • 示例:当设备状态变化时,多个处理器(如日志记录器、安全检查器等)可以顺序处理该状态变化。

示例

以下是一个结合状态模式和工厂模式、策略模式的示例:

#include <iostream>
#include <memory>
#include <string>// 策略接口
class InitializationStrategy {
public:virtual void initialize() = 0;virtual ~InitializationStrategy() = default;
};// 具体策略:快速初始化
class QuickInitialization : public InitializationStrategy {
public:void initialize() override {std::cout << "Quick initialization" << std::endl;}
};// 具体策略:完整初始化
class FullInitialization : public InitializationStrategy {
public:void initialize() override {std::cout << "Full initialization" << std::endl;}
};// 状态接口
class State {
public:virtual ~State() = default;virtual void onUnplug(DeviceDriver* driver) = 0;virtual void onPlugIn(DeviceDriver* driver) = 0;virtual void onInitialize(DeviceDriver* driver) = 0;virtual void onReady(DeviceDriver* driver) = 0;
};// 状态工厂类
class StateFactory {
public:static std::shared_ptr<State> createUnpluggedState() {return std::make_shared<Unplugged>();}static std::shared_ptr<State> createPlugInState() {return std::make_shared<PlugIn>();}static std::shared_ptr<State> createInitializeState() {return std::make_shared<Initialize>();}static std::shared_ptr<State> createReadyState() {return std::make_shared<Ready>();}
};// 设备驱动类
class DeviceDriver {
public:DeviceDriver() : currentState(StateFactory::createUnpluggedState()) {}void unplug() {currentState->onUnplug(this);}void plugIn() {currentState->onPlugIn(this);}void initialize() {currentState->onInitialize(this);}void ready() {currentState->onReady(this);}void setState(const std::shared_ptr<State>& state) {currentState = state;}private:std::shared_ptr<State> currentState;
};// 具体状态:未插入
class Unplugged : public State {
public:void onUnplug(DeviceDriver* driver) override {std::cout << "Already unplugged." << std::endl;}void onPlugIn(DeviceDriver* driver) override {std::cout << "Device plugged in." << std::endl;driver->setState(StateFactory::createPlugInState());}void onInitialize(DeviceDriver* driver) override {std::cout << "Cannot initialize. Device not plugged in." << std::endl;}void onReady(DeviceDriver* driver) override {std::cout << "Cannot be ready. Device not plugged in." << std::endl;}
};// 具体状态:已插入
class PlugIn : public State {
public:PlugIn() : strategy(std::make_unique<QuickInitialization>()) {}void onUnplug(DeviceDriver* driver) override {std::cout << "Device unplugged." << std::endl;driver->setState(StateFactory::createUnpluggedState());}void onPlugIn(DeviceDriver* driver) override {std::cout << "Already plugged in." << std::endl;}void onInitialize(DeviceDriver* driver) override {std::cout << "Device initialized." << std::endl;strategy->initialize();driver->setState(StateFactory::createInitializeState());}void onReady(DeviceDriver* driver) override {std::cout << "Cannot be ready. Device not initialized." << std::endl;}private:std::unique_ptr<InitializationStrategy> strategy;
};// 具体状态:已初始化
class Initialize : public State {
public:void onUnplug(DeviceDriver* driver) override {std::cout << "Device unplugged." << std::endl;driver->setState(StateFactory::createUnpluggedState());}void onPlugIn(DeviceDriver* driver) override {std::cout << "Already plugged in and initialized." << std::endl;}void onInitialize(DeviceDriver* driver) override {std::cout << "Already initialized." << std::endl;}void onReady(DeviceDriver* driver) override {std::cout << "Device is ready to use." << std::endl;driver->setState(StateFactory::createReadyState());}
};// 具体状态:已准备好
class Ready : public State {
public:void onUnplug(DeviceDriver* driver) override {std::cout << "Device unplugged." << std::endl;driver->setState(StateFactory::createUnpluggedState());}void onPlugIn(DeviceDriver* driver) override {std::cout << "Device is already ready." << std::endl;}void onInitialize(DeviceDriver* driver) override {std::cout << "Device is already initialized and ready." << std::endl;}void onReady(DeviceDriver* driver) override {std::cout << "Device is already ready." << std::endl;}
};int main() {DeviceDriver driver;// 模拟设备插拔和状态转移driver.plugIn();driver.initialize();driver.ready();driver.unplug();driver.plugIn();driver.ready();return 0;
}

代码说明

  1. 策略接口 InitializationStrategy

    • 定义了一个初始化策略接口,包含一个 initialize 方法。
    • 具体策略类 QuickInitialization 和 FullInitialization 实现了不同的初始化策略。
  2. 状态工厂类 StateFactory

    • 提供静态方法创建不同状态的实例。
  3. 具体状态类 PlugIn

    • 包含一个策略对象 strategy,在 onInitialize 方法中使用该策略进行初始化。
  4. 主函数 main

    • 创建一个 DeviceDriver 对象,并模拟设备的插拔和状态转移过程。

通过这种方式,状态模式与工厂模式和策略模式协同使用,使得代码更加灵活和可维护。

相关文章:

C++软件设计模式之状态模式

在C设计模式中&#xff0c;状态模式&#xff08;State Pattern&#xff09;是一种行为设计模式&#xff0c;它允许对象在内部状态改变时改变其行为&#xff0c;使对象看起来似乎修改了其类。状态模式的主要动机、意图和适用场合如下&#xff1a; 动机 在面向对象的设计中&…...

Microsoft Visual Studio中的/MT, /MTd,/MD,/MDd分别是什么意思?

1. /MT&#xff0c;/MTd&#xff0c;/MD&#xff0c;/MDd的含义 /MT&#xff0c;/MTd&#xff0c;/MD&#xff0c;/MDd是 Microsoft Visual C 编译器的运行时库链接选项。它们决定了程序如何链接 C 运行时库&#xff08;CRT&#xff09;。具体含义如下&#xff1a; /MT&#x…...

谷粒商城项目125-spring整合high-level-client

新年快乐! 致2025年还在努力学习的你! 你已经很努力了&#xff0c;今晚就让自己好好休息一晚吧! 在后端中选用哪种elasticsearch客户端&#xff1f; elasticsearch可以通过9200或者9300端口进行操作 1&#xff09;9300&#xff1a;TCP spring-data-elasticsearch:transport-…...

日期时间选择(设置禁用状态)

目录 1.element文档需要 2.禁用所有过去的时间 3.设置指定日期的禁用时间 <template><div class"block"><span class"demonstration">起始日期时刻为 12:00:00</span><el-date-pickerv-model"value1"type"dat…...

基于SpringBoot的题库管理系统的设计与实现(源码+SQL+LW+部署讲解)

文章目录 摘 要1. 第1章 选题背景及研究意义1.1 选题背景1.2 研究意义1.3 论文结构安排 2. 第2章 相关开发技术2.1 前端技术2.2 后端技术2.3 数据库技术 3. 第3章 可行性及需求分析3.1 可行性分析3.2 系统需求分析 4. 第4章 系统概要设计4.1 系统功能模块设计4.2 数据库设计 5.…...

钉钉h5微应用安卓报错error29 ios报错error3 加上报错52013,签名校验失败 (前端)

这两个都是应为 免登报错52013&#xff0c;签名校验失败 用户后端签名使用的url地址和前端访问地址需要严格一致&#xff0c;包括端口号。前端部分可以用alert显示出当前的location.href&#xff0c;后端部分请在签名的时候打印日志。 访问通过反向代理服务器、各种NAT等场景下…...

Vue.js组件开发-客户端如何限制刷新Token次数

在Vue.js组件开发中&#xff0c;限制刷新Token的次数是一个重要的安全措施&#xff0c;可以防止恶意用户或攻击者无限次尝试刷新Token。 客户端限制 在客户端&#xff0c;可以通过Vuex、localStorage或sessionStorage等存储机制来跟踪刷新Token的尝试次数。以下是一个基本的实…...

Linux上安装jdk

在线环境的话&#xff0c;通过命令下载&#xff0c;离线环境的话&#xff0c;组要自行去oracle官网下载后上传 wget --no-check-certificate --no-cookies --header "Cookie: oraclelicenseaccept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jd…...

Ardunio BLE keyboard 库的使用

为了开发一个 ardunio 的蓝牙选歌器&#xff0c;网络上普遍推荐使用&#xff1a; https://github.com/T-vK/ESP32-BLE-Keyboard 结果搞了好几天&#xff0c;就是不行。最后发现&#xff0c;下面两点非常重要&#xff1a; 使用 NimBle-ardunio 库这个库目前是2.1.2 &#xff…...

django --递归查询评论

表数据 树状结构 action(methods(GET, ), detailFalse) def get_info_pinglun(self, request, *args, **kwargs) -> Response:根据评论id查所有回复params wenxian_pinglun_id --> 评论id;wenxian_pinglun_id self.request.GET.get(wenxian_pinglun_id)results se…...

【开源免费】基于SpringBoot+Vue.JS音乐网站(JAVA毕业设计)

本文项目编号 T 109 &#xff0c;文末自助获取源码 \color{red}{T109&#xff0c;文末自助获取源码} T109&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...

SUBSTRING_INDEX()在MySQL中的用法

语法&#xff1a; SUBSTRING_INDEX() 是 MySQL 中的一个字符串函数&#xff0c;它返回一个字符串&#xff0c;该字符串包含从字符串的开始或结束到指定的子字符串出现指定次数为止的部分。这个函数的语法如下&#xff1a; SUBSTRING_INDEX(string, delimiter, count)string&a…...

对45家“AI+安全”产品/方案的分析

一. 关键洞察 “AI+安全”创新非常活跃,一片百家争鸣之势,赛道选择上,以事件分诊Incident Triage、 安全辅助Security Copilots、自动化Automation三者为主为主,这充分反映了当前安全运营的主要需求,在产品理念选择上以 AI 和 自动化为主,这确实又切合上了在关键…...

Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(1):Oracle Dataguard 概述

Oracle Dataguard&#xff08;主库为 Oracle 11g 单节点&#xff09;配置详解&#xff08;1&#xff09;&#xff1a;Oracle Dataguard 概述 目录 Oracle Dataguard&#xff08;主库为 Oracle 11g 单节点&#xff09;配置详解&#xff08;1&#xff09;&#xff1a;Oracle Data…...

Pycharm 中 virtualenv、pipenv、conda 虚拟环境的用法

文章目录 前言虚拟环境的通俗介绍虚拟环境和非虚拟环境该怎么选?通过 Virtualenv 方式创建虚拟环境通过 Pipenv 方式创建虚拟环境通过 Conda 方式创建虚拟环境前言 在网上找了好一些资料,发现介绍 Pycharm 虚拟环境的不多,查了一些资料,并做个总结。 本文主要是介绍 Pycha…...

UNI-APP弹窗

组件代码 <template><view><!-- 蒙版 --><view class"mask" click"close()" v-show"tanchuang"></view><!-- 弹窗 --><view class"pop" :style"{height:height*0.8 px,top:tanchuang?…...

【大模型实战篇】LLaMA Factory微调ChatGLM-4-9B模型

1. 背景介绍 虽然现在大模型微调的文章很多&#xff0c;但纸上得来终觉浅&#xff0c;大模型微调的体感还是需要自己亲自上手实操过&#xff0c;才能有一些自己的感悟和直觉。这次我们选择使用llama_factory来微调chatglm-4-9B大模型。 之前微调我们是用两块3090GPU显卡&…...

【Cesium】三、实现开场动画效果

文章目录 实现效果实现方法实现代码组件化 实现效果 实现方法 Cesium官方提供了Camera的flyTo方法实现了飞向目的地的动画效果。 官方API&#xff1a;传送门 这里只需要用到目的地&#xff08;destination&#xff09;和持续时间&#xff08;duration&#xff09;这两个参数…...

#渗透测试#红蓝攻防#红队打点web服务突破口总结01

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…...

适用于项目经理的跨团队协作实践:Atlassian Jira与Confluence集成

适用于项目经理的跨团队协作实践&#xff1a;Atlassian Jira与Confluence集成 现代项目经理的核心职责是提供可视性、保持团队一致&#xff0c;并确保团队拥有交付出色工作所需的资源。在过去几年中&#xff0c;由于分布式团队的需求不断增加&#xff0c;项目经理这一角色已迅速…...

智能家居体验大变革 博联 AI 方案让智能不再繁琐

1. 全球AI技术发展背景及智能家居市场趋势 人工智能&#xff08;AI&#xff09;技术的飞速发展正在推动全球各行业的数字化转型。国际电信联盟与德勤联合发布《人工智能向善影响》报告指出&#xff0c;全球94%的商界领袖认为&#xff0c;人工智能技术对于其企业在未来5年内的发…...

云计算与服务是什么

云计算与服务是一个广泛而深入的话题&#xff0c;涵盖了云计算的基本概念、特点、服务类型以及应用场景等多个方面。以下是对云计算与服务的详细解析&#xff1a; ### 一、云计算的基本概念 云计算是一种基于互联网的计算方式&#xff0c;它通过动态易扩展且虚拟化的资源&…...

接口测试面试题

接口测试在软件测试中占据重要位置&#xff0c;无论是功能测试还是性能测试&#xff0c;接口的稳定性至关重要。以下总结了一些常见的接口测试面试题&#xff0c;帮助你从容应对面试挑战&#xff01; 面试官常说&#xff1a;“接口测试是测试的重头戏&#xff0c;了解接口的设计…...

【Cesium】六、实现鹰眼地图(三维)与主图联动效果

文章目录 一、前言二、效果三、实现方法2.1 思路2.2 方法2.3 使用 App.vue 一、前言 上一篇文章&#xff1a;【Cesium】五、地图实现鹰眼效果&#xff08;三维&#xff09;&#xff0c;虽然实现了3D 的鸟瞰图效果&#xff0c;但是只有鸟瞰图跟着 主地图在动&#xff0c;如果 在…...

ESLint+Prettier的配置

ESLintPrettier的配置 安装插件 ​​​​​​ 在settings.json中写下配置 {// tab自动转换标签"emmet.triggerExpansionOnTab": true,"workbench.colorTheme": "Default Dark","editor.tabSize": 2,"editor.fontSize": …...

4.微服务灰度发布落地实践(消息队列增强)

文章目录 前言问题分析消息队列特性分析kafkarocketmqrabbitmq 发布订阅公共抽象发送端订阅端 前言 消息队列是一种用于在应用程序的不同组件或系统之间传递消息的通信机制。它通过将消息存储在一个队列中&#xff0c;确保消息能够可靠地从发送方传递到接收方&#xff0c;即使…...

【从零开始入门unity游戏开发之——C#篇35】C#自定义类实现Sort自定义排序

文章目录 一、List<T>自带的排序方法1、List<T>调用Sort()排序2、 能够使用 Sort() 方法进行排序的本质 二、自定义类的排序1、通过实现泛型IComparable<T> 接口&#xff08;1&#xff09;示例&#xff08;2&#xff09;直接调用 int 类型的 CompareTo 方法进…...

音频进阶学习九——离散时间傅里叶变换DTFT

文章目录 前言一、DTFT的解释1.DTFT公式2.DTFT右边释义1&#xff09; 复指数 e − j ω n e^{-j\omega n} e−jωn2&#xff09;序列与复指数相乘 x [ n ] ∗ e − j ω n x[n]*e^{-j\omega n} x[n]∗e−jωn复指数序列复数的共轭正交正交集 3&#xff09;复指数序列求和 3.DTF…...

连接github和ai的桥梁:GitIngest

Git ingest GitIngest - 将任何 Github 仓库转变为适合 LLM 的友好型提示文本 (https://github.com/cyclotruc/gitingest) 输入 Github 地址或者名称&#xff0c;GitIngest 就会提供该仓库的总结、目录结构、仓库内容的文本内容 你可以复制这些文本与 AI 大模型更好地对话...

Pytorch使用手册-DCGAN 指南(专题十四)

1. Introduction 本教程将通过一个示例介绍 DCGANs(深度卷积生成对抗网络)。我们将训练一个生成对抗网络(GAN),在给它展示大量真实名人照片后,它能够生成新的“名人”图片。这里的大部分代码来源于 PyTorch 官方示例中的 DCGAN 实现,而本文档将对该实现进行详细解释,并…...