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

C++命令模式 指挥家:掌控命令模式之美

C++指挥家:掌控命令模式之美 (C++ Conductor: Master the Beauty of Command Pattern

  • 一、引言 (Introduction)
    • 1.1 命令模式概述 (Overview of Command Pattern)
    • 1.2 命令模式的应用场景 (Application Scenarios of Command Pattern)
  • 二、命令模式的基本概念 (Basic Concepts of Command Pattern)
    • 2.1 接收者(Receiver)
    • 2.2 命令(Command)
    • 2.3 调用者(Invoker)
    • 2.4 具体命令(Concrete Command)
    • 2.5 命令模式UML图
  • 三、C++实现命令模式 (Implementing Command Pattern in C++)
    • 3.1 设计接收者类 (Designing the Receiver Class)
    • 3.2 设计命令接口 (Designing the Command Interface)
    • 3.3 实现具体命令类 (Implementing the Concrete Command Classes)
  • 四、命令模式的优缺点 (Pros and Cons of Command Pattern)
    • 4.1 命令模式的优点 (Advantages of Command Pattern)
    • 4.2 命令模式的缺点 (Disadvantages of Command Pattern)
  • 五、命令模式的应用实例 (Application Examples of Command Pattern)
    • 5.1 图形编辑器 (Graphic Editor)
    • 5.2 播放器控制 (Player Control)
  • 六、结语

一、引言 (Introduction)

1.1 命令模式概述 (Overview of Command Pattern)

命令模式(Command Pattern)是一种行为型设计模式,主要用于将请求发送者和请求接收者解耦。该模式涉及四个角色:接收者(Receiver)、命令(Command)、调用者(Invoker)和具体命令(Concrete Command)。命令模式的核心思想是将请求封装成对象,从而实现对操作的高度灵活性。

Command Pattern is a behavioral design pattern that primarily decouples the request sender and the request receiver. It involves four roles: Receiver, Command, Invoker, and Concrete Command. The core idea of the command pattern is to encapsulate requests into objects, thereby achieving high flexibility for operations.

1.2 命令模式的应用场景 (Application Scenarios of Command Pattern)

命令模式适用于以下几种场景:

  1. 当需要将请求发送者和请求接收者解耦时,可以使用命令模式。这使得调用者和接收者之间的联系变得更加松散,增强了系统的灵活性。
  2. 当需要实现对请求的撤销、重做或者存储请求操作历史记录等功能时,命令模式可以为你提供帮助。
  3. 当系统需要支持一组可配置的操作时,命令模式可以实现动态地组合操作和修改操作顺序。
  4. 当系统需要实现异步操作或者需要将操作放入队列中进行处理时,命令模式也很适用。

Command pattern is suitable for the following scenarios:

  1. When you need to decouple the request sender and request receiver, you can use the command pattern. This makes the connection between the caller and the receiver more relaxed, enhancing the flexibility of the system.
  2. When you need to implement undo, redo, or store request operation history, the command pattern can help you.
  3. When the system needs to support a set of configurable operations, the command pattern can dynamically combine and modify operation orders.
  4. When the system needs to implement asynchronous operations or needs to put operations into a queue for processing, the command pattern is also very suitable.

二、命令模式的基本概念 (Basic Concepts of Command Pattern)

2.1 接收者(Receiver)

接收者(Receiver)是命令模式中负责执行具体操作的对象。它包含了所有操作的具体实现方法。通常情况下,接收者与命令本身是分离的,它们之间不直接交互。

Receiver is the object responsible for executing specific operations in the Command Pattern. It contains all the specific implementation methods of the operations. Generally, the receiver is separate from the command itself, and they do not interact directly.

2.2 命令(Command)

命令(Command)是一个抽象类或接口,它定义了一个名为execute()的方法,该方法接受一个接收者(Receiver)实例作为参数。命令对象用于封装执行某个操作的请求,将请求与实际的操作解耦。

Command is an abstract class or interface that defines a method called execute(), which takes a Receiver instance as a parameter. The command object is used to encapsulate a request to perform an operation, decoupling the request from the actual operation.

2.3 调用者(Invoker)

调用者(Invoker)负责发起请求和执行命令。它包含了一个或多个命令对象,并且在需要时触发命令对象的execute()方法。调用者不需要关心命令的具体实现,只需要知道如何发起请求。

Invoker is responsible for initiating requests and executing commands. It contains one or more command objects and triggers the execute() method of the command object when needed. The invoker does not need to care about the specific implementation of the command, it only needs to know how to initiate a request.

2.4 具体命令(Concrete Command)

具体命令(Concrete Command)是命令接口的具体实现。每一个具体命令都包含了一个接收者(Receiver)实例,该实例负责执行与该命令相关的操作。当调用者触发execute()方法时,具体命令将调用接收者的相应方法以完成实际操作。

Concrete Command is the specific implementation of the Command interface. Each concrete command contains a Receiver instance responsible for performing the operation associated with the command. When the invoker triggers the execute() method, the concrete command will call the corresponding method of the receiver to complete the actual operation.

2.5 命令模式UML图

命令模式的UML图包含以下几个关键部分:

  1. Command(抽象命令):一个接口或抽象类,定义了execute()方法。
  2. ConcreteCommand(具体命令):实现Command接口的具体类,实现了execute()方法,并持有Receiver的引用。
  3. Receiver(接收者):执行具体操作的类,包含具体操作的实现方法。
  4. Invoker(调用者):持有Command对象的类,负责发起请求和执行命令。

以下是命令模式的UML图:

+-------------------+      +-------------------+      +--------------------+
|    Invoker        |      |     Command       |      |    Receiver        |
+-------------------+      +-------------------+      +--------------------+
| +setCommand(cmd)  |<-----| +execute() : void |----->| +action() : void   |
| +executeCommand() |      +-------------------+      +--------------------+
+-------------------+              ^                            ^|                            |+------------------+          +---------------+| ConcreteCommand  |          | SpecificReceiver |+------------------+          +---------------+| +execute() : void |          | +action() : void |+------------------+          +---------------+

在此UML图中,Invoker类通过setCommand()方法设置ConcreteCommand对象,并通过executeCommand()方法触发ConcreteCommand对象的execute()方法。ConcreteCommand类实现了Command接口,并在其execute()方法中调用Receiver类的具体操作。具体的Receiver类包含了操作的实现方法。

三、C++实现命令模式 (Implementing Command Pattern in C++)

3.1 设计接收者类 (Designing the Receiver Class)

首先,我们需要设计一个接收者类,这个类包含了具体操作的实现方法。在本例中,我们将创建一个名为Light的类,它有一个turnOn()方法来表示开灯操作,一个turnOff()方法表示关灯操作。

#include <iostream>class Light {
public:void turnOn() {std::cout << "Light is on." << std::endl;}void turnOff() {std::cout << "Light is off." << std::endl;}
};

在这个例子中,Light类代表接收者(Receiver),负责执行与开灯和关灯相关的操作。

3.2 设计命令接口 (Designing the Command Interface)

接下来,我们需要定义一个命令接口。在C++中,我们可以使用抽象类来表示接口。我们将创建一个名为Command的抽象类,其中包含一个纯虚函数execute()

class Command {
public:virtual void execute() = 0;
};

3.3 实现具体命令类 (Implementing the Concrete Command Classes)

现在,我们需要为每个具体操作创建具体命令类。在本例中,我们需要创建两个具体命令类:TurnOnLightCommandTurnOffLightCommand。这两个类都继承自Command抽象类,并实现execute()方法。每个具体命令类都包含一个Light对象的引用,用于执行实际的操作。

class TurnOnLightCommand : public Command {
private:Light &light;public:TurnOnLightCommand(Light &light) : light(light) {}void execute() override {light.turnOn();}
};class TurnOffLightCommand : public Command {
private:Light &light;public:TurnOffLightCommand(Light &light) : light(light) {}void execute() override {light.turnOff();}
};

在这个例子中,我们通过构造函数将Light对象的引用传递给具体命令类,使得具体命令类能够执行实际操作。TurnOnLightCommand类实现了execute()方法,调用light.turnOn();而TurnOffLightCommand类实现了execute()方法,调用light.turnOff()

四、命令模式的优缺点 (Pros and Cons of Command Pattern)

4.1 命令模式的优点 (Advantages of Command Pattern)

  1. 解耦请求发送者与请求接收者:命令模式将请求发送者(Invoker)与请求接收者(Receiver)解耦,使它们之间的联系变得更加松散,有助于系统的灵活性和可扩展性。
  2. 易于扩展新命令:使用命令模式时,如果需要添加新的操作,只需要实现一个新的具体命令类即可,无需修改已有的代码。
  3. 支持撤销、重做等操作:命令模式可以轻松地实现撤销、重做等功能。通过存储已执行的命令对象,并实现相应的撤销和重做方法,可以实现这些功能。
  4. 支持将命令放入队列和异步执行:命令模式可以将多个命令放入队列中进行处理。此外,它还可以支持异步操作,将操作放入后台线程中执行。

4.2 命令模式的缺点 (Disadvantages of Command Pattern)

  1. 增加了系统的复杂性:命令模式引入了许多新的类,如抽象命令类、具体命令类等。这使得系统的复杂性增加,增加了学习和理解的难度。
  2. 可能导致类数量过多:由于每个操作都需要一个具体命令类,所以当有大量操作时,可能导致类数量急剧增加,使系统变得庞大和难以维护。
  3. 增加了间接性:命令模式将请求发送者与接收者之间增加了一个抽象层次。这虽然带来了一定程度的解耦,但也增加了系统的间接性,可能导致调试和定位问题更加困难。

尽管命令模式有一些缺点,但在合适的场景下,它仍然是一种非常有用的设计模式。在需要解耦发送者和接收者、易于扩展新命令或支持撤销、重做等功能的系统中,命令模式是一个很好的选择。

五、命令模式的应用实例 (Application Examples of Command Pattern)

5.1 图形编辑器 (Graphic Editor)

首先,我们创建一个简化版的图形编辑器,实现如下功能:添加圆形、删除圆形、打印当前图形。

#include <iostream>
#include <vector>
#include <memory> // C++11特性: shared_ptr
#include <algorithm> // C++14特性: std::find_if, std::remove_if
#include <any> // C++17特性: std::anyclass Circle {
public:Circle(int id) : id(id) {}void draw() const {std::cout << "Draw circle with ID: " << id << std::endl;}int getID() const {return id;}private:int id;
};class GraphicEditor {
public:void addCircle(std::shared_ptr<Circle> circle) {circles.push_back(circle);}void removeCircle(int id) {circles.erase(std::remove_if(circles.begin(), circles.end(),[id](const auto& circle) { return circle->getID() == id; }), // C++14特性: auto, lambda expressioncircles.end());}void printCircles() const {std::cout << "Current circles:" << std::endl;for (const auto& circle : circles) { // C++11特性: auto, range-based for loopcircle->draw();}}private:std::vector<std::shared_ptr<Circle>> circles;
};

现在,我们将使用命令模式重构图形编辑器。

// Command Interface
class Command {
public:virtual ~Command() = default; // C++11特性: 默认函数=defaultvirtual void execute() = 0;
};// Concrete Command: AddCircleCommand
class AddCircleCommand : public Command {
public:AddCircleCommand(GraphicEditor& editor, int id) : editor(editor), circle(std::make_shared<Circle>(id)) {} // C++14特性: std::make_sharedvoid execute() override {editor.addCircle(circle);}private:GraphicEditor& editor;std::shared_ptr<Circle> circle;
};// Concrete Command: RemoveCircleCommand
class RemoveCircleCommand : public Command {
public:RemoveCircleCommand(GraphicEditor& editor, int id) : editor(editor), id(id) {}void execute() override {editor.removeCircle(id);}private:GraphicEditor& editor;int id;
};// Invoker: CommandHandler
class CommandHandler {
public:void setCommand(std::shared_ptr<Command> command) {this->command = command;}void executeCommand() {if (command) {command->execute();}}private:std::shared_ptr<Command> command;
};int main() {GraphicEditor editor;CommandHandler handler;auto addCircleCommand = std::make_shared<AddCircleCommand>(editor, 1);auto removeCircleCommand = std::make_shared<RemoveCircleCommand>(editor, 1);handler.setCommand(addCircleCircleCommand);handler.executeCommand(); // 添加圆形editor.printCircles(); // 输出: Draw circle with ID: 1handler.setCommand(addCircleCommand);handler.executeCommand(); // 再次添加圆形editor.printCircles(); // 输出: Draw circle with ID: 1, Draw circle with ID: 1handler.setCommand(removeCircleCommand);handler.executeCommand(); // 删除圆形editor.printCircles(); // 输出: Draw circle with ID: 1std::any userData; // C++17特性: std::anyuserData = 42;std::cout << "UserData: " << std::any_cast<int>(userData) << std::endl; // 输出: UserData: 42return 0;}

在上面的代码中,我们使用了命令模式重构了简化版的图形编辑器,并展示了如何添加和删除圆形。同时,我们使用了C++11,C++14和C++17的特性,如shared_ptrautolambda expressionmake_sharedany等,并提供了详细注释。

5.2 播放器控制 (Player Control)

首先,我们创建一个简化版的播放器:

#include <iostream>
#include <memory> // C++11特性: shared_ptr
#include <any> // C++17特性: std::any
#include <optional> // C++17特性: std::optionalclass Player {
public:void play() {std::cout << "Playing..." << std::endl;}void pause() {std::cout << "Paused." << std::endl;}void stop() {std::cout << "Stopped." << std::endl;}
};

现在,我们将使用命令模式重构播放器控制:

// Command Interface
class Command {
public:virtual ~Command() = default; // C++11特性: 默认函数=defaultvirtual void execute() = 0;
};// Concrete Command: PlayCommand
class PlayCommand : public Command {
public:explicit PlayCommand(Player& player) : player(player) {} // C++11特性: explicit关键字void execute() override {player.play();}private:Player& player;
};// Concrete Command: PauseCommand
class PauseCommand : public Command {
public:explicit PauseCommand(Player& player) : player(player) {}void execute() override {player.pause();}private:Player& player;
};// Concrete Command: StopCommand
class StopCommand : public Command {
public:explicit StopCommand(Player& player) : player(player) {}void execute() override {player.stop();}private:Player& player;
};// Invoker: RemoteController
class RemoteController {
public:void setCommand(std::shared_ptr<Command> command) {this->command = command;}void pressButton() {if (command) {command->execute();}}private:std::shared_ptr<Command> command;
};int main() {Player player;RemoteController remote;auto playCommand = std::make_shared<PlayCommand>(player);auto pauseCommand = std::make_shared<PauseCommand>(player);auto stopCommand = std::make_shared<StopCommand>(player);remote.setCommand(playCommand);remote.pressButton(); // 输出: Playing...remote.setCommand(pauseCommand);remote.pressButton(); // 输出: Paused.remote.setCommand(stopCommand);remote.pressButton(); // 输出: Stopped.// C++17特性: std::optionalstd::optional<int> maybeValue;if (!maybeValue.has_value()) { // 当前没有值maybeValue = 42;}if (maybeValue.has_value()) { // 现在有值了std::cout << "Optional value: " << maybeValue.value() << std::endl; // 输出: Optional value: 42}return 0;
}

六、结语

在本篇博客中,我们详细介绍了C++中命令模式的概念、原理、优缺点以及在图形编辑器和播放器控制中的应用。通过学习命令模式,我们不仅可以提高自己的编程技巧,还可以更好地理解面向对象设计原则,提升编程思维。

从心理学角度来看,学习和理解设计模式对个人和团队都具有积极意义。首先,设计模式提供了一种解决问题的共同语言,有助于团队成员之间的有效沟通,降低沟通成本。其次,设计模式可以提高程序员的自信心,因为它们代表了行业内公认的最佳实践。使用设计模式可以使程序员确信自己的解决方案是高效、稳定的,从而提高工作满意度。

此外,学习设计模式有助于培养程序员的创新思维。了解现有的设计模式可以帮助我们站在巨人的肩膀上,以更高的起点开始思考问题。在学习和理解现有设计模式的基础上,我们可以更好地发现潜在的设计问题,甚至可能提出新的设计模式。

总之,本篇博客通过深入浅出的介绍和示例,让读者更好地理解和掌握命令模式。从心理学角度看,学习命令模式不仅有助于提高编程技能,还可以促进团队协作,激发创新思维。希望本篇博客能给您带来启发和收获,祝您学习愉快!

相关文章:

C++命令模式 指挥家:掌控命令模式之美

C指挥家&#xff1a;掌控命令模式之美 (C Conductor: Master the Beauty of Command Pattern一、引言 (Introduction)1.1 命令模式概述 (Overview of Command Pattern)1.2 命令模式的应用场景 (Application Scenarios of Command Pattern)二、命令模式的基本概念 (Basic Concep…...

学会 制作极简搜索浏览器 —— 并将 ChatGPT 接入浏览器

前期回顾 Vue3 Ts Vite pnpm 项目中集成 —— eslint 、prettier、stylelint、husky、commitizen_0.活在风浪里的博客-CSDN博客搭建VIte Ts Vue3项目并集成eslint 、prettier、stylelint、huskyhttps://blog.csdn.net/m0_57904695/article/details/129950163?spm1001.2…...

NumPy 秘籍中文第二版:六、特殊数组和通用函数

原文&#xff1a;NumPy Cookbook - Second Edition 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 在本章中&#xff0c;我们将介绍以下秘籍&#xff1a; 创建通用函数查找勾股三元组用chararray执行字符串操作创建一个遮罩数组忽略负值和极值使用recarray函数创建一…...

各种交叉编译工具链的区别

目录 1 命名规则 2 实例 2.1 arm-none-eabi-gcc 2.2 arm-none-linux-gnueabi-gcc 2.3 arm-eabi-gcc 2.4 armcc 2.5 arm-none-uclinuxeabi-gcc 和 arm-none-symbianelf-gcc 3 gnueabi和gnueabihf的区别(硬浮点、软浮点) 4 Linaro公司出品的交叉编译工具链 5 ARM公司出…...

密度聚类算法(DBSCAN)实验案例

密度聚类算法&#xff08;DBSCAN&#xff09;实验案例 描述 DBSCAN是一种强大的基于密度的聚类算法&#xff0c;从直观效果上看&#xff0c;DBSCAN算法可以找到样本点的全部密集区域&#xff0c;并把这些密集区域当做一个一个的聚类簇。DBSCAN的一个巨大优势是可以对任意形状…...

第07章_面向对象编程(进阶)

第07章_面向对象编程(进阶) 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 关键字&#xff1a;this 1.1 this是什么&#xff1f; 在Java中&#xff0c;this关键字不算难理解…...

异常的讲解(2)

目录 throws异常处理 基本介绍 throws异常处理注意事项和使用细节 自定义异常 基本概念 自定义异常的步骤 throw 和throws的区别 本章作业 第一题 第二题 第三题 第四题 throws异常处理 基本介绍 1)如果一个方法(中的语句执行时)可能生成某种异常&#xff0c;但是…...

jvm内存结构

1. 栈 程序计数器 2. 虚拟机栈 3. 本地方法栈 4. 堆 5. 方法区 1.2栈内存溢出 栈帧过多导致栈内存溢出 /*** 演示栈内存溢出 java.lang.StackOverflowError* -Xss256k*/ public class Demo1_2 {private static int count;public static void main(String[] args) {try {meth…...

要刹车?生成式AI迎新规、行业连发ChatGPT“警报”、多国考虑严监管

4月13日消息&#xff0c;据中国移动通信联合会元宇宙产业工作委员会网站&#xff0c;中国移动通信联合会元宇宙产业工作委员会、中国通信工业协会区块链专业委员会等&#xff0c;共同发布“关于元宇宙生成式人工智能&#xff08;类 ChatGPT&#xff09;应用的行业提示”。提示内…...

轻松掌握Qt FTP 机制:实现高效文件传输

轻松掌握Qt FTP&#xff1a;实现高效文件传输一、简介&#xff08;Introduction&#xff09;1.1 文件传输协议&#xff08;FTP&#xff09;Qt及其网络模块&#xff08;Qt and its Network Module&#xff09;QNetwork:二、QNetworkAccessManager上传实例&#xff08;Qt FTP Upl…...

用AI帮我写一篇关于FPGA的文章,并推荐最热门的FPGA开源项目

FPGA定义 FPGA&#xff08;Field Programmable Gate Array&#xff09;是一种可编程逻辑器件&#xff0c;可以在硬件电路中实现各种不同的逻辑功能。与ASIC&#xff08;Application Specific Integrated Circuit&#xff0c;特定应用集成电路&#xff09;相比&#xff0c;FPGA…...

从兴趣或问题出发

当我们还沉寂在移动互联网给生活带来众多便利中&#xff0c;以 ChartGPT 为代表的 AI 时代已彻底到来。科技的发展&#xff0c;时刻在改变着我们的生活&#xff0c;我们需要不断地学习新知识和掌握新技能才能享受变化带来的便利&#xff0c;以及自身不被社会淘汰。 因此&#…...

C++ | 探究拷贝对象时的一些编译器优化

&#x1f451;作者主页&#xff1a;烽起黎明 &#x1f3e0;学习社区&#xff1a;烈火神盾 &#x1f517;专栏链接&#xff1a;C 文章目录前言一、传值传参二、传引用传参三、传值返回拷贝构造和赋值重载的辨析四、传引用返回【❌】五、传匿名对象返回六、总计与提炼前言 在传参…...

linux工具gcc/g++/gdb/git的使用

目录 gcc/g 基本概念 指令集 函数库 &#xff08;重要&#xff09; gdb使用 基本概念 指令集 项目自动化构建工具make/makefile 进度条小程序 ​编辑 git三板斧 创建仓库 git add git commit git push git status git log gcc/g 基本概念 gcc/g称为编译器…...

Direct3D 12——纹理——纹理

纹理不同于缓冲区资源&#xff0c;因为缓冲区资源仅存储数据数组&#xff0c;而纹理却可以具有多个mipmap层级(后 文有介绍)&#xff0c;GPU会基于这个层级进行相应的特殊操作&#xff0c;例如运用过滤器以及多重采样。支持这些特殊 的操作纹理资源都被限定为一些特定的数据格式…...

产品经理必读 | 俞军产品经理十二条军规

最近在学习《俞军产品方法论》&#xff0c;觉得俞军总结的十二条产品经理原则非常受用&#xff0c;分享给大家。 01. 产品经理首先是产品的深度用户 自己设计的产品都没使用过的产品经理&#xff0c;如何明白用户使用的问题&#xff0c;如何解决问题&#xff0c;所以产品经理肯…...

【机器视觉1】光源介绍与选择

文章目录一、常见照明光源类型二、照明光源对比三、照明技术3.1 亮视野与暗视野3.2 低角度照明3.3 前向光直射照明3.4 前向光漫射照明3.5 背光照明-测量系统的最佳选择3.6 颜色与补色示例3.7 偏光技术应用四、镜头4.1 镜头的几个概念4.2 影响图像质量的关键因素4.3 成像尺寸4.4…...

【三十天精通Vue 3】第十一天 Vue 3 过渡和动画详解

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录引言一、Vue 3 过度和动画概述1.1过度和动画的简介二、Vue 3 过度2…...

基于多种流量检测引擎识别pcap数据包中的威胁

在很多的场景下&#xff0c;会需要根据数据包判断数据包中存在的威胁。针对已有的数据包&#xff0c;如何判断数据包是何种攻击呢&#xff1f; 方法一可以根据经验&#xff0c;对于常见的WEB类型的攻击&#xff0c;比如SQL注入&#xff0c;命令执行等攻击&#xff0c;是比较容…...

第02章_变量与运算符

第02章_变量与运算符 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 关键字&#xff08;keyword&#xff09; 定义&#xff1a;被Java语言赋予了特殊含义&#xff0c;用做专门…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...