设计模式.
设计模式
- 一、介绍
- 二、六大原则
- 1、单一职责原则(Single Responsibility Principle, SRP)
- 2、开闭原则(Open-Closed Principle, OCP)
- 3、里氏替换原则(Liskov Substitution Principle, LSP)
- 4、接口隔离原则(Interface Segregation Principle, ISP)
- 5、依赖倒置原则(Dependency Inversion Principle, DIP)
- 6、迪米特法则(Law of Demeter, LoD)
- 三、单例模式
- 1、介绍
- 2、模式
- 3、示例
- (1)饿汉模式
- (2)懒汉模式
- 四、工厂模式
- 1、介绍
- 2、实现方式
- 3、示例
- 五、建造者模式
- 1、介绍
- 2、实现方式
- 3、示例
- 六、代理模式
- 1、介绍
- 2、主要角色
- 3、示例
一、介绍
- 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它旨在使代码更加可重用、易于理解和维护,并提高代码的可靠性。
二、六大原则
1、单一职责原则(Single Responsibility Principle, SRP)
- 一个类应该只有一个引起它变化的原因,即一个类只负责一项功能或职责。
- 如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或抑制该类完成其他职责的能力。因此,将类的职责分离到不同的类中,可以提高代码的可读性、可维护性和可扩展性。
2、开闭原则(Open-Closed Principle, OCP)
- 软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
- 当需要增加新功能时,应该通过扩展已有的软件实体来实现,而不是修改已有的代码。这可以通过使用接口、抽象类或组合/聚合等方式来实现。
3、里氏替换原则(Liskov Substitution Principle, LSP)
- 子类必须能够替换其基类而不会引起程序行为的改变。
- 在软件设计中,应优先使用对象组合而不是类继承,以避免破坏基类已有的功能。子类应该实现父类的抽象方法,但不得重写父类的非抽象方法。子类可以增加自己特有的方法,并且子类方法的前置条件(输入参数)应该比父类方法的输入参数类型更宽松,方法的后置条件(返回值)应该比父类返回值类型更严格。
4、接口隔离原则(Interface Segregation Principle, ISP)
- 客户端不应该依赖它不需要的接口,即使用多个隔离的接口比使用单个的接口好。
- 一个接口应该只包含客户感兴趣的方法,而不是将所有可能的方法都放在一个接口中。这样可以降低类之间的耦合度,便于维护。
5、依赖倒置原则(Dependency Inversion Principle, DIP)
- 高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
- 这意味着我们应该通过抽象层(如接口或抽象类)来定义模块间的依赖关系,而不是直接依赖具体的实现类。依赖倒置原则本质上就是面向接口编程,它提高了系统的灵活性和可扩展性。
6、迪米特法则(Law of Demeter, LoD)
- 一个实体应该尽量少的与其他实体发生相互作用,使得系统功能模块相对独立。
- 迪米特法则也称为最少知道原则,它要求一个类应该尽量少的了解其他类的内部细节,只与必要的类进行交互。这样可以降低系统的复杂性,提高系统的可维护性和可扩展性。
三、单例模式
1、介绍
- 单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。在需要控制资源访问、实现全局状态管理、或者在整个应用程序生命周期中需要保持某些对象唯一性的场景中非常有用。
关键点 | 作用 |
---|---|
私有构造函数 | 防止外部通过 new 关键字创建实例 |
静态实例变量 | 用于存储类的唯一实例 |
公共静态方法 | 提供一个全局访问点来获取实例 |
删除拷贝构造和赋值运算符重载 | 防止创建多个实例和对象间的赋值操作 |
2、模式
懒汉模式 | 饿汉模式 | |
---|---|---|
创建时机 | 第一次访问时 | 类加载时 |
线程安全 | 不安全,需要使用同步锁等方式来确保线程安全 | 线程安全 |
优点 | 延迟加载,节省资源 | 实现简单,线程安全 |
缺点 | 实现复杂,线程不安全 | 无论是否需要使用都会占用资源,可能导致资源浪费 |
3、示例
(1)饿汉模式
#include <iostream>class Singleton
{
private:static Singleton _eton;private:Singleton() : _data(666) { std::cout << "单例Singleton 饿汉, 构造函数" << std::endl; };~Singleton() {};Singleton(const Singleton &) = delete;Singleton &operator=(const Singleton &) = delete;private:int _data;public:static Singleton &getInstance(){return _eton;}int getData(){return _data;}
};Singleton Singleton::_eton;int main()
{std::cout << Singleton::getInstance().getData() <<std::endl;return 0;
}
(2)懒汉模式
class Singleton
{
private:Singleton() : _data(666) { std::cout << "单例Singleton 懒汉, 构造函数" << std::endl; };~Singleton() {};Singleton(const Singleton &) = delete;Singleton &operator=(const Singleton &) = delete;private:int _data;public:static Singleton &getInstance(){static Singleton _eton;return _eton;}int getData(){return _data;}
};
- 上方代码在C++11后才是线程安全的,因为C++11局部的静态变量的创建是线程安全的。
四、工厂模式
1、介绍
- 工厂模式(Factory Pattern)是一种创建型设计模式,它旨在定义一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂模式让类的实例化推迟到其子类。这样可以将对象的实例化与客户端代码的耦合度降到最低,同时也提供了一种可扩展的方式来创建对象。
主要角色 | 作用 |
---|---|
抽象产品(AbstractProduct) | 定义产品的接口,是工厂方法模式所创建对象的公共父类 |
具体产品(ConcreteProduct) | 实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建 |
抽象工厂(AbstractFactory) | 在抽象工厂类中声明了工厂方法,用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口 |
具体工厂(ConcreteFactory) | 实现了抽象工厂中声明的工厂方法,并可由客户端调用,返回一个具体产品类的实例 |
2、实现方式
- 简单工厂模式(Simple Factory Pattern):通过一个工厂类来创建对象,客户端通过传递不同的参数给工厂类,工厂类根据参数的不同来创建不同的对象实例。优点是客户端代码简单,隐藏了具体对象的创建细节;缺点是当需要添加新的产品时,需要修改工厂类的代码,违反了开闭原则。
- 工厂方法模式(Factory Method Pattern):将对象的创建延迟到子类中去实现,即定义一个创建对象的接口,但让子类决定实例化哪个类。客户端通过调用工厂方法来创建对象,具体的实例化过程由子类负责。这样可以解决简单工厂模式中的缺点,使得系统更具灵活性和可扩展性。
- 抽象工厂模式(Abstract Factory Pattern):提供一个接口用于创建一系列相关或依赖对象的家族,而不需要指定具体的类。与工厂方法模式相比,抽象工厂模式是针对多个产品等级结构的,可以创建不同产品族的全部产品。这种模式适用于需要在运行时切换不同产品族的场景,但增加新的产品族往往不太容易。
3、示例
- 简单工厂模式
#include <iostream>
#include <memory>
#include <string>class Fruit
{
public:virtual void name() = 0;
};class Apple : public Fruit
{
public:void name() override{std::cout << "i am a apple" << std::endl;}
};class Pineapple : public Fruit
{
public:void name() override{std::cout << "i am a pineapple" << std::endl;}
};class FruitFactory
{
public:static std::shared_ptr<Fruit> create(const std::string& name){if(name == "apple")return std::make_shared<Apple>();else if(name == "pineapple")return std::make_shared<Pineapple>();return std::shared_ptr<Fruit>();}
};int main()
{std::shared_ptr<Fruit> fruit = FruitFactory::create("apple");fruit->name();fruit.reset();fruit = FruitFactory::create("pineapple");fruit->name();return 0;
}
- 工厂方法模式
class Factory
{
public:virtual std::shared_ptr<Fruit> create() = 0;
};class AppleFactory : public Factory
{
public:std::shared_ptr<Fruit> create(){return std::make_shared<Apple>();}
};class PineappleFactory : public Factory
{
public:std::shared_ptr<Fruit> create(){return std::make_shared<Pineapple>();}
};int main()
{std::shared_ptr<Factory> fruitFactory(new AppleFactory());std::shared_ptr<Fruit> fruit = fruitFactory->create();fruit->name();fruitFactory.reset(new PineappleFactory());fruit = fruitFactory->create();fruit->name();return 0;
}
- 抽象工厂模式
class Animal
{
public:virtual void voice() = 0;
};class Dragon : public Animal
{
public:void voice() override{std::cout << "恶龙咆哮" << std::endl;}
};class Wolf : public Animal
{
public:void voice() override{std::cout << "我一定会回来的" << std::endl;}
};class Factory
{
public:virtual std::shared_ptr<Fruit> getFruit(const std::string& name) = 0;virtual std::shared_ptr<Animal> getAnimal(const std::string& name) = 0;
};class FruitFactory : public Factory
{
public:std::shared_ptr<Fruit> getFruit(const std::string& name) override{if(name == "apple")return std::make_shared<Apple>();else if(name == "pineapple")return std::make_shared<Pineapple>();return std::shared_ptr<Fruit>(); // 需用shared_ptr}std::shared_ptr<Animal> getAnimal(const std::string& name) override{return std::shared_ptr<Animal>(); // 需用shared_ptr}
};class AnimalFactory : public Factory
{
public:std::shared_ptr<Fruit> getFruit(const std::string& name) override{return std::shared_ptr<Fruit>();}std::shared_ptr<Animal> getAnimal(const std::string& name) override{if(name == "dragon")return std::make_shared<Dragon>();else if(name == "wolf")return std::make_shared<Wolf>();return std::shared_ptr<Animal>();}
};class FactoryProducer
{
public:static std::shared_ptr<Factory> getFactory(const std::string& name) // 可以声明为静态,这样调用时就不用创建对象{if(name == "fruit")return std::make_shared<FruitFactory>();else if(name == "animal")return std::make_shared<AnimalFactory>();return std::shared_ptr<Factory>();}
};int main()
{std::shared_ptr<Factory> factory = FactoryProducer::getFactory("fruit");std::shared_ptr<Fruit> fruit = factory->getFruit("apple");fruit->name();fruit.reset();fruit = factory->getFruit("pineapple");fruit->name();std::cout << "\n";factory = FactoryProducer::getFactory("animal");std::shared_ptr<Animal> animal = factory->getAnimal("dragon");animal->voice();animal.reset();animal = factory->getAnimal("wolf");animal->voice();return 0;
}
五、建造者模式
1、介绍
- 建造者模式(Builder Pattern)是一种创建型设计模式,它将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。该模式允许用户通过指定复杂对象的类型和内容来构建它们,而无需知道内部的具体构建细节。
- 建造者模式的目的是将对象的构建过程拆分成多个简单的步骤,并允许用户通过调用这些步骤来逐步构建对象。
主要角色 | 说明 |
---|---|
产品(Product) | 要创建的复杂对象 |
抽象建造者(Builder) | 定义一个用于创建和装配产品各个部件的抽象接口 |
具体建造者(ConcreteBuilder) | 实现抽象建造者接口,并构建和装配具体产品的各个部件。同时,它还提供一个方法来返回最终创建的产品 |
指挥者(Director) | 构造一个使用抽象建造者接口的对象。它主要用于创建一个复杂对象,并控制其构建过程。指挥者并不与具体的产品类发生关系,而是通过一个抽象建造者接口来间接创建产品 |
- 与工厂模式的区别:建造者模式与工厂模式在创建对象方面有所不同。工厂模式主要用于创建具有共同接口或基类的不同实例,而建造者模式则更关注于对象的复杂构建过程和各个部件的组装。
2、实现方式
- 在建造者模式中,通常会有一个具体的产品类,该类包含了产品的各个属性和方法。然后,会有一个或多个具体建造者类,这些类实现了抽象建造者接口,并提供了构建产品各个部件的方法。指挥者类则负责调用这些方法来逐步构建产品。
3、示例
#include <iostream>
#include <string>
#include <memory>class Computer
{
public:void setBoard(const std::string& board) // 派生类不重写,不要加virtual{_board = board; // 没加virtual,需要对成员变量进行赋值}void setDisplay(const std::string& display){_display = display;}virtual void setOs() = 0;std::string show(){// std::cout<<_board<<" "<<_display<<std::endl;std::string comp = "computer:\n "; // 换行之和多加一个空格,否则下一句中文可能乱码comp += "\tboard: " + _board + " \n ";comp += "\tdisplay: " + _display + "\n ";comp += "\tos: " + _os + "\n";// std::cout << comp << std::endl;return comp;}
protected:std::string _board;std::string _display;std::string _os;
};class Legion : public Computer
{
public:void setOs(){_os = "Windows 11";}
};class Builder
{
public:virtual void buildBoard(const std::string& board) = 0;virtual void buildDisplay(const std::string& display) = 0;virtual void buildOs() = 0; // os也需要调用virtual std::shared_ptr<Computer> build() = 0;
};class LegionBuilder : public Builder
{
public:LegionBuilder():_cp(new Legion()){} // 构造对象void buildBoard(const std::string& board){_cp->setBoard(board);}void buildDisplay(const std::string& display){_cp->setDisplay(display);}void buildOs(){_cp->setOs();}std::shared_ptr<Computer> build(){return _cp;}private:std::shared_ptr<Computer> _cp; // 类型需要是Computer
};class Direct
{
public:Direct(Builder* bp):_bp(bp){}void construct(const std::string& board, const std::string& display){_bp->buildBoard(board);_bp->buildDisplay(display);_bp->buildOs();}
private:std::shared_ptr<Builder> _bp;
};int main()
{Builder* bp = new LegionBuilder();std::unique_ptr<Direct> dup(new Direct(bp));dup->construct("联想", "三星");std::shared_ptr<Computer> cp = bp->build();std::cout << cp->show();// cp->show();return 0;
}
六、代理模式
1、介绍
- 代理模式(Proxy Pattern)是程序设计中的一种结构型设计模式,其为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
- 代理模式的目的是在不修改目标对象代码的前提下,通过代理对象来控制对目标对象的访问,并增加额外的功能或提供间接访问。
2、主要角色
- 抽象主题(Subject):声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题。
- 真实主题(RealSubject):实现了抽象主题接口,是真正执行任务的对象。
- 代理主题(Proxy):代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象;代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主题;控制真实主题的应用,负责在需要的时候创建真实主题对象(和删除真实主题对象)。代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作,而不是单纯的将调用传递给真实主题对象。
3、示例
#include <iostream>class RentHouse
{
public:virtual void rentHouse() = 0;
};class Landlord : public RentHouse
{
public:void rentHouse(){std::cout << "Landlord rent the house" << std::endl;}
};class Intermediary : public RentHouse
{
public:void rentHouse(){std::cout << "发布租房起始" << std::endl;std::cout << "带领租客看房" << std::endl;_ld.rentHouse();std::cout << "后期维修相关" << std::endl;}
private:Landlord _ld;
};int main()
{Intermediary im;im.rentHouse();return 0;
}
本文到这里就结束了,如有错误或者不清楚的地方欢迎评论或者私信
本文只是在编写项目,学习过程中所做的总结,不会涉及过深的概念
创作不易,如果觉得博主写得不错,请点赞、收藏加关注支持一下💕💕💕
相关文章:

设计模式.
设计模式 一、介绍二、六大原则1、单一职责原则(Single Responsibility Principle, SRP)2、开闭原则(Open-Closed Principle, OCP)3、里氏替换原则(Liskov Substitution Principle, LSP)4、接口隔离原则&am…...

使用PyCharm创建项目以及如何注释代码
创建好项目后会出现如下图所示的画面,我们可以通过在项目文件夹上点击鼠标右键,选择“New”菜单下的“Python File”来创建一个 Python 文件,在给文件命名时建议使用英文字母和下划线的组合,创建好的 Python 文件会自动打开&#…...

LabVIEW与PLC交互
一、写法 写命令立即读出 写命令后立即读出,在同一时间不能有多个地方写入,因此需要在整个写入后读出过程加锁 项目中会存在多个循环并行执行该VI,轮询PLC指令 在锁内耗时,就是TCP读写的实际耗时为5-8ms,在主VI六个…...

Idea 2024.3 使用CodeGPT插件整合Deepseek
哈喽,大家好,我是浮云,最近国产大模型Deepseek异常火爆,作为程序员我也试着玩了一下,首先作为简单的使用,大家进入官网,点击开始对话即可进行简单的聊天使用,点击获取手机app即可安装…...
[论文笔记] Deepseek-R1R1-zero技术报告阅读
启发: 1、SFT&RL的训练数据使用CoT输出的格式,先思考再回答,大大提升模型的数学与推理能力。 2、RL训练使用群体相对策略优化(GRPO),奖励模型是规则驱动,准确性奖励和格式化奖励。 1. 总体概述 背景与目标 报告聚焦于利用强化学习(RL)提升大型语言模型(LLMs)…...

VUE之组件通信(三)
1、$refs与$parent 1)概述: $refs用于:父——>子。$parent用于:子——>父。 2)原理如下: 属性说明$refs值为对象,包含所有被ref属性标识的DOM元素或组件实例。$parent值为对象&#x…...
【Redis实战】投票功能
1. 前言 现在就来实践一下如何使用 Redis 来解决实际问题,市面上很多网站都提供了投票功能,比如 Stack OverFlow 以及 Reddit 网站都提供了根据文章的发布时间以及投票数计算出一个评分,然后根据这个评分进行文章的展示顺序。本文就简单演示…...
linux常用基础命令 最新1
常用命令 查看当前目录下个各个文件大小查看当前系统储存使用情况查看当前路径删除当前目录下所有包含".log"的文件linux开机启动jar更改自动配置文件后操作关闭自启动linux静默启动java服务查询端口被占用查看软件版本重启关机开机启动取别名清空当前行创建文件touc…...

UnityShader学习笔记——多种光源
——内容源自唐老狮的shader课程 目录 1.光源类型 2.判断光源类型 2.1.在哪判断 2.2.如何判断 3.光照衰减 3.1.基本概念 3.2.unity中的光照衰减 3.3.光源空间变换矩阵 4.点光源衰减计算 5.聚光灯衰减计算 5.1.聚光灯的cookie(灯光遮罩) 5.2.聚…...

深入浅出谈VR(虚拟现实、VR镜头)
1、VR是什么鬼? 近两年VR这次词火遍网上网下,到底什么是VR?VR是“Virtual Reality”,中文名字是虚拟现实,是指采用计算机技术为核心的现代高科技手段生成一种虚拟环境,用户借助特殊的输入/输出设备&#x…...

项目2 车牌检测
检测车牌 1. 基本思想2. 基础知识2.1 YOLOV5(参考鱼苗检测)2.1.1 模型 省略2.1.2 输入输出 省略2.1.3 损失函数 省略2.2 LPRNet2.2.1 模型2.2.2 输入输出2.2.3 损失函数3. 流程3.1 数据处理3.1.1 YOLOV5数据处理3.2.2 LPRNet数据处理3.2 训练3.2.1 YOLOV5训练 省略3.2.2 LPRN…...

Linux: 网络基础
1.协议 为什么要有协议:减少通信成本。所有的网络问题,本质是传输距离变长了。 什么是协议:用计算机语言表达的约定。 2.分层 软件设计方面的优势—低耦合。 一般我们的分层依据:功能比较集中,耦合度比较高的模块层…...
【实战篇】巧用 DeepSeek,让 Excel 数据处理更高效
一、为何选择用 DeepSeek 处理 Excel 在日常工作与生活里,Excel 是我们频繁使用的工具。不管是统计公司销售数据、分析学生成绩,还是梳理个人财务状况,Excel 凭借其强大的功能,如数据排序、筛选和简单公式计算,为我们提供了诸多便利。但当面对复杂的数据处理任务,比如从…...

Flink CDC YAML:面向数据集成的 API 设计
摘要:本文整理自阿里云智能集团 、Flink PMC Member & Committer 徐榜江(雪尽)老师在 Flink Forward Asia 2024 数据集成(一)专场中的分享。主要分为以下四个方面: Flink CDC YAML API Transform A…...
RabbitMQ技术深度解析:打造高效消息传递系统
引言 在当前的分布式系统架构中,消息队列作为一种高效的消息传递机制,扮演着越来越重要的角色。RabbitMQ,作为广泛使用的开源消息代理,以其高可用性、扩展性和灵活性赢得了众多开发者的青睐。本文将深入探讨RabbitMQ的核心概念、…...
DeepSeek与人工智能的结合:探索搜索技术的未来
云边有个稻草人-CSDN博客 目录 引言 一、DeepSeek的技术背景 1.1 传统搜索引擎的局限性 1.2 深度学习在搜索中的优势 二、DeepSeek与人工智能的结合 2.1 自然语言处理(NLP) 示例代码:基于BERT的语义搜索 2.2 多模态搜索 示例代码&…...

TAPEX:通过神经SQL执行器学习的表格预训练
摘要 近年来,语言模型预训练的进展通过利用大规模非结构化文本数据取得了巨大成功。然而,由于缺乏大规模高质量的表格数据,在结构化表格数据上应用预训练仍然是一个挑战。本文提出了TAPEX,通过在一个合成语料库上学习神经SQL执行…...

Qt:Qt基础介绍
目录 Qt背景介绍 什么是Qt Qt的发展史 Qt支持的平台 Qt版本 Qt的优点 Qt的应用场景 Qt的成功案例 Qt的发展前景及就业分析 Qt背景介绍 什么是Qt Qt是⼀个跨平台的C图形用户界面应用程序框架。它为应用程序开发者提供了建立艺术级图形界面所需的所有功能。它是完全面向…...
加速度计信号处理
【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)_加速度计滤波器-CSDN博客 https://wenku.baidu.com/view/622d38b90f22590102020740be1e650e52eacff9.html?_wkts_1738906719916&bdQ…...

基于SpringBoot养老院平台系统功能实现六
一、前言介绍: 1.1 项目摘要 随着全球人口老龄化的不断加剧,养老服务需求日益增长。特别是在中国,随着经济的快速发展和人民生活水平的提高,老年人口数量不断增加,对养老服务的质量和效率提出了更高的要求。传统的养…...

Conmi的正确答案——Rider中添加icon作为exe的图标
C#版本:.net 8.0 Rider版本:#RD-243.22562.250(非商业使用版) 1、添加图标到解决方案下: 2、打开“App.xaml”配置文件,添加配置: <Applicationx:Class"ComTransmit.App"xmlns&q…...
机试题——DNS本地缓存
题目描述 正在开发一个DNS本地缓存系统。在互联网中,DNS(Domain Name System)用于将域名(例如www.example.com)解析为IP地址,以便将请求发送到正确的服务器上。通常情况下,DNS请求会发送到互联…...
Day38【AI思考】-彻底打通线性数据结构间的血脉联系
文章目录 **彻底打通线性数据结构间的血脉联系****数据结构家族谱系图****一、线性表(老祖宗的规矩)****核心特征** **二、嫡系血脉解析**1. **数组(规矩森严的长子)**2. **链表(灵活变通的次子)** **三、庶…...

【LeetCode】152、乘积最大子数组
【LeetCode】152、乘积最大子数组 文章目录 一、dp1.1 dp1.2 简化代码 二、多语言解法 一、dp 1.1 dp 从前向后遍历, 当遍历到 nums[i] 时, 有如下三种情况 能得到最大值: 只使用 nums[i], 例如 [0.1, 0.3, 0.2, 100] 则 [100] 是最大值使用 max(nums[0…i-1]) * nums[i], 例…...

[MRCTF2020]Ez_bypass1(md5绕过)
[MRCTF2020]Ez_bypass1(md5绕过) 这道题就是要绕过md5强类型比较,但是本身又不相等: md5无法处理数组,如果传入的是数组进行md5加密,会直接放回NULL,两个NuLL相比较会等于true; 所以?id[]1&gg…...

MySQL 缓存机制与架构解析
目录 一、MySQL缓存机制概述 二、MySQL整体架构 三、SQL查询执行全流程 四、MySQL 8.0为何移除查询缓存? 五、MySQL 8.0前的查询缓存配置 六、替代方案:应用层缓存与优化建议 总结 一、MySQL缓存机制概述 MySQL的缓存机制旨在提升数据访问效率&am…...

LabVIEW自定义测量参数怎么设置?
以下通过一个温度采集案例,说明在 LabVIEW 中设置自定义测量参数的具体方法: 案例背景 假设使用 NI USB-6009 数据采集卡 和 热电偶传感器 监测温度,需自定义以下参数: 采样率:1 kHz 输入量程:0~10 V&a…...

海思的一站式集成环境Hispark Studio更新了
HiSpark Studio是海思提供的面向智能设备开发者提供一站式集成开发环境,支持代码编辑、编译、烧录和调试等功能。我以前在评测星闪芯片的时候用过,当时写了篇博客:【星闪开发连载】WS63E开发板Windows环境的构建_hispark studio-CSDN博客。那…...
TresJS:用Vue组件构建3D场景的新选择
在当今数字化时代,3D图形技术正以前所未有的速度发展,从游戏开发到虚拟现实(VR)、增强现实(AR),再到各种沉浸式体验,3D技术的应用场景日益丰富。TresJS作为一款基于Three.js的Web3D开…...

Axure设计教程:动态排名图(中继器实现)
一、开篇 在Axure原型设计中,动态图表是展示数据和交互效果的重要元素。今天,我们将学习如何使用中继器来创建一个动态的排名图,该图表不仅支持自动轮播,还可以手动切换,极大地增强了用户交互体验。此教程旨在提供一个…...