C++设计模式(更新中)

文章目录

  • 1、创建型模式
    • 1.1 简单工厂(Simple Factory)
      • (1)示例
      • (2)总结
    • 1.2 工厂方法(Factory Method)
      • (1)示例
      • (2)总结
    • 1.3 抽象工厂(Abstract Factory)
      • (1)示例
      • (2)总结
    • 1.4 建造者(Builder)
      • (1)示例
      • (2)总结

1、创建型模式

1.1 简单工厂(Simple Factory)

简单工厂模式通过一个工厂类负责对象的创建,客户端只需提供参数,工厂类根据条件返回相应的对象。这种方式可以减少客户端对具体实现的依赖。

核心结构

  1. 工厂类:负责根据传入的参数生成具体对象。
  2. 产品抽象基类:定义所有产品的公共接口。
  3. 产品类:具体的实现类,继承自产品基类。
  4. 客户端:通过工厂类创建产品对象并调用其方法。
    在这里插入图片描述

(1)示例

假设正在开发一个工具库,工具种类包含绘制工具 (DrawTool) 和擦除工具 (EraseTool)。为了简化工具对象的创建和使用,可以通过简单工厂模式来生成这些工具。

库代码实现

  • 工具抽象类和具体工具类
    Tool.h:为了方便,这里没有分文件编写,实际中也可以分成Tool.h + Tool.cpp,工具太多也可以每个具体工具和工具接口类全部分开编写。之后的示例代码也是一样。

    #pragma once
    #include <iostream>// 工具基类
    class Tool
    {
    public:virtual void UseTool() = 0; virtual ~Tool() = default;
    };// 具体工具类1 - 绘制工具
    class DrawTool : public Tool
    {
    public:void UseTool() override{std::cout << "Using Draw Tool!" << std::endl;}
    };// 具体工具类2 - 擦除工具
    class EraseTool : public Tool
    {
    public:void UseTool() override{std::cout << "Using Erase Tool!" << std::endl;}
    };
    
  • 工厂类 (ToolFactory.hToolFactory.cpp)
    ToolFactory.h

    #pragma once
    #include <memory>
    #include "Tool.h"// 工厂类,用于创建工具对象
    class ToolFactory
    {
    public:enum class ToolType{Draw,Erase};// 简单工厂创建工具的静态方法static std::unique_ptr<Tool> CreateTool(ToolType type);
    };
    

    ToolFactory.cpp

    #include "ToolFactory.h"std::unique_ptr<Tool> ToolFactory::CreateTool(ToolType type)
    {switch (type){case ToolType::Draw:return std::make_unique<DrawTool>();case ToolType::Erase:return std::make_unique<EraseTool>();default:return nullptr;}
    }
    

使用者代码

使用者只需要引入 ToolFactory.h,通过工厂类创建工具对象,而不需要知道具体的工具类 DrawToolEraseTool。这减少了客户端和库中具体实现的依赖关系。

从下面代码,可以看到,实际上使用者这边还是需要依赖于工具基类的信息的(没有包含Tool.h是因为工厂类已经包含了),但是不需要知道具体的工具类的信息

Main.cpp

#include "ToolFactory.h" int main()
{// 使用工厂创建绘制工具std::unique_ptr<Tool> tool = ToolFactory::CreateTool(ToolFactory::ToolType::Draw);if (tool)tool->UseTool(); // 使用工厂创建擦除工具tool = ToolFactory::CreateTool(ToolFactory::ToolType::Erase);if (tool)tool->UseTool();return 0;
}

(2)总结

  • 优点:

    • 减少依赖:客户端只需依赖工厂类与产品基类,而不需要依赖具体产品类。
    • 解耦创建与使用:工厂类封装了创建细节,客户端只负责使用产品。
  • 缺点:

    • 违反开闭原则:每次添加新的工具类型,必须修改工厂类的 CreateTool 方法,添加一条新的case:,导致不符合 “对修改关闭,对扩展开放”的原则。在扩展性和代码维护上有一定的缺点,特别是在需要频繁添加新工具类型的情况下。
    • 工厂类复杂化:工厂类会随产品种类的增加而变得复杂。

1.2 工厂方法(Factory Method)

工厂方法模式通过将创建对象的逻辑推迟到子类中,从而解决简单工厂模式违反开闭原则的问题。它的核心理念是将工厂类拆分成多个具体工厂,每个工厂类负责创建某种特定产品。

核心结构

抽象产品 + 具体产品,抽象工厂 + 具体工厂
在这里插入图片描述

(1)示例

重构1.1中的示例代码,工具基类及其子类保持不变,但工厂类需要改造成每种产品对应一个工厂子类,各自负责产品的创建。

  • 工厂类ToolFactory.h
    #pragma once
    #include <memory>
    #include "Tool.h"class ToolFactory 
    {
    public:virtual std::unique_ptr<Tool> CreateTool() = 0;virtual ~ToolFactory() = default;
    };class DrawToolFactory : public ToolFactory 
    {
    public:std::unique_ptr<Tool> CreateTool() override {return std::make_unique<DrawTool>();}
    };class EraseToolFactory : public ToolFactory 
    {
    public:std::unique_ptr<Tool> CreateTool() override {return std::make_unique<EraseTool>();}
    };
    
  • 客户端使用main.cpp
    #include "ToolFactory.h"int main()
    {// 创建绘制工具工厂对象std::unique_ptr<ToolFactory> drawFactory = std::make_unique<DrawToolFactory>();// 创建绘制工具std::unique_ptr<Tool> drawTool = drawFactory->CreateTool();if (drawTool)drawTool->UseTool();// 创建擦除工具工厂对象std::unique_ptr<ToolFactory> eraseFactory = std::make_unique<EraseToolFactory>();// 创建擦除工具std::unique_ptr<Tool> eraseTool = eraseFactory->CreateTool();if (eraseTool)eraseTool->UseTool();return 0;
    }
    

(2)总结

  • 优点

    • 符合开闭原则:新增产品时,只需新增对应的工厂类,而无需修改已有代码。
    • 单一职责:每个工厂类只负责创建一种产品,职责更为明确。
    • 可扩展性:更方便地增加新产品和新工厂,且代码修改局部化,减少潜在错误。
  • 缺点

    • 类的增加:每种产品都需要对应的工厂类,会导致类的数量增加,增加系统的复杂性。
    • 复杂度提升:对于简单的对象创建场景,工厂方法模式可能显得过于复杂,因为每个具体产品都需要单独的工厂类。
    • 职责分散:每个工厂类只负责创建某种具体产品,可能导致系统中存在较多分散的创建逻辑,维护起来可能不便。

1.3 抽象工厂(Abstract Factory)

在某些情况下,我们需要创建一组相关或依赖的对象,而不仅仅是单个对象。工厂方法模式虽然可以创建单个产品,但如果需要创建多个产品,并且这些产品之间存在某种强关联(比如 UI 系统中不同平台的按钮、文本框等,比如windows平台的按钮必须搭配同平台的文本框),工厂方法模式就显得不足了。

抽象工厂模式提供一个接口,用于创建相关联的对象族,而不指定它们的具体类。它解决了创建多类相关产品的问题,而不是单个产品。

核心结构:

  1. 抽象工厂类:定义创建一系列相关产品的接口。
  2. 具体工厂类:实现抽象工厂的接口,负责创建一系列具体产品。
  3. 抽象产品类:为不同产品提供统一的接口。
  4. 具体产品类:每个具体工厂创建的不同产品实现类。
  5. 客户端:通过抽象工厂接口来获取相关联的产品。
    在这里插入图片描述

(1)示例

假设现在有4种具体工具产品,分别是2D绘制工具、2D擦除工具、3D绘制工具、3D擦除工具,正常情况来说,2D绘制工具跟2D擦除工具肯定是配套的,如果工厂方法来创建,就可能混淆使用,而抽象工厂则可以避免这种错误产生

  • Tool.h:这里从Tool接口类直接派生了4个工具,也可以这样做(根据需求灵活处理):

    • 定义2DTool抽象类和3DTool抽象类,然后再分别派生2个具体工具类出来
    • 定义DrawTool抽象类和EraseTool抽象类,然后再分别派生2个具体工具类出来
    #pragma once
    #include <iostream>// 抽象产品类 - 工具
    class Tool 
    {
    public:virtual void UseTool() = 0;virtual ~Tool() = default;
    };// 具体产品类 - 2D绘制工具
    class Draw2DTool : public Tool 
    {
    public:void UseTool() override {std::cout << "Using 2D Draw Tool!" << std::endl;}
    };// 具体产品类 - 2D擦除工具
    class Erase2DTool : public Tool 
    {
    public:void UseTool() override {std::cout << "Using 2D Erase Tool!" << std::endl;}
    };// 具体产品类 - 3D绘制工具
    class Draw3DTool : public Tool 
    {
    public:void UseTool() override {std::cout << "Using 3D Draw Tool!" << std::endl;}
    };// 具体产品类 - 3D擦除工具
    class Erase3DTool : public Tool 
    {
    public:void UseTool() override {std::cout << "Using 3D Erase Tool!" << std::endl;}
    };
    
  • Factory.h

    #pragma once
    #include <memory>
    #include "Tool.h"// 抽象工厂类
    class ToolFactory 
    {
    public:virtual std::unique_ptr<Tool> CreateDrawTool() = 0;virtual std::unique_ptr<Tool> CreateEraseTool() = 0;virtual ~ToolFactory() = default;
    };// 具体工厂类 - 2D工具工厂
    class Tool2DFactory : public ToolFactory 
    {
    public:std::unique_ptr<Tool> CreateDrawTool() override {return std::make_unique<Draw2DTool>();}std::unique_ptr<Tool> CreateEraseTool() override {return std::make_unique<Erase2DTool>();}
    };// 具体工厂类 - 3D工具工厂
    class Tool3DFactory : public ToolFactory 
    {
    public:std::unique_ptr<Tool> CreateDrawTool() override {return std::make_unique<Draw3DTool>();}std::unique_ptr<Tool> CreateEraseTool() override {return std::make_unique<Erase3DTool>();}
    };
    
  • main.cpp

    // Main.cpp
    #include "Factory.h"int main() {// 创建2D工厂std::unique_ptr<ToolFactory> factory2D = std::make_unique<Tool2DFactory>();std::unique_ptr<Tool> tool = factory2D->CreateDrawTool();tool->UseTool(); tool = factory2D->CreateEraseTool();tool->UseTool(); // 创建3D工厂std::unique_ptr<ToolFactory> factory3D = std::make_unique<Tool3DFactory>();tool = factory3D->CreateDrawTool();tool->UseTool();  tool = factory3D->CreateEraseTool();tool->UseTool(); return 0;
    }
    

(2)总结

  • 优点

    • 产品族一致性:通过具体工厂类,确保了 2D 和 3D 工具的内部一致性,避免在客户端中创建不兼容的工具(如混用 2D 和 3D 工具)。
    • 在新增工具方面,遵守开闭原则:新增其他绘制工具类型时,比如一个4D工具,只需额外实现新的具体工厂类和对应的产品类,保证了系统的可扩展性。
    • 减少客户端依赖:客户端只依赖抽象工厂和抽象产品,而不需要关心具体实现的细节,符合依赖倒置原则。
  • 缺点

    • 复杂性:增加了工厂类和产品类的数量,系统结构更加复杂,尤其当产品族多时会造成一定的维护压力。
    • 在新增每种工具的功能时,不遵守开闭原则:比如现在的每种工具套件都支持绘制、擦除工具,我还想新增一个修改工具,则需要修改每一个工厂类和每一个产品类的代码。
    • 灵活性降低:所有工厂创建的产品都是预定义的,无法灵活组合不同种类的产品。

1.4 建造者(Builder)

建造者模式的作用是将复杂对象的组装过程和对象的实际表示区分开来。这样,相同的组装步骤可以用来制造出不同的对象表现形式。这种模式非常适合于那些由多个可选组件组成的复杂对象。通过分步骤地构建每个组件,我们可以根据需要灵活地组合出各种不同的对象。

建造者模式的核心理念是通过引入一个建造者(Builder)类,负责构建对象的各个部分,而不是在一个复杂的构造函数中完成所有工作。它能够分阶段创建对象,允许客户端在构建过程中灵活选择和配置对象的组件。该模式还允许通过实现不同的具体建造者,来生成不同类型或版本的产品对象。

直接上具体案例,来理解这个模式

(1)示例

组装电脑,电脑有很多可定制的部件(如CPU、GPU、硬盘、内存等),对于不同的需求(比如游戏电脑、办公电脑),需要选用不同的性能、品牌的部件,建造者模式可以灵活地应对这些变化。

在这里插入图片描述
类之间的关系

  1. Director:通过 Builder 来控制建造流程,确保每个步骤按顺序调用。它不需要知道具体的产品细节,只需要负责调用 Builder 提供的接口。
  2. Builder:定义了构建的接口,具体的建造步骤(如 BuildCPU()BuildGPU() 等)。
  3. ConcreteBuilder:实现 Builder 接口的具体类,负责创建不同类型的产品,如游戏电脑和办公电脑。每个 ConcreteBuilder 实现了相同的建造步骤,但生成不同的结果。
  4. Product:是最终生成的对象,它包含了多个部分(CPU、GPU、Memory 等),由 ConcreteBuilder 一步步构建。
#include <iostream>
#include <string>// 产品类:电脑
class Computer 
{
public:void SetCPU(const std::string& cpu) { CPU = cpu; }void SetGPU(const std::string& gpu) { GPU = gpu; }void SetMemory(const std::string& memory) { Memory = memory; }void SetStorage(const std::string& storage) { Storage = storage; }void ShowSpecifications() const {std::cout << "Computer Specifications:\n";std::cout << "CPU: " << CPU << "\n";std::cout << "GPU: " << GPU << "\n";std::cout << "Memory: " << Memory << "\n";std::cout << "Storage: " << Storage << "\n";}private:std::string CPU;std::string GPU;std::string Memory;std::string Storage;
};// 抽象建造者:定义创建产品的步骤
class ComputerBuilder 
{
public:virtual ~ComputerBuilder() = default;virtual void BuildCPU() = 0;virtual void BuildGPU() = 0;virtual void BuildMemory() = 0;virtual void BuildStorage() = 0;virtual Computer* GetResult() = 0;
};// 具体建造者:游戏电脑
class GamingComputerBuilder : public ComputerBuilder 
{
private:Computer* computer;public:GamingComputerBuilder() {computer = new Computer();}~GamingComputerBuilder() {delete computer;}void BuildCPU() override {computer->SetCPU("i9");}void BuildGPU() override {computer->SetGPU("RTX4090 ");}void BuildMemory() override {computer->SetMemory("16GB DDR4");}void BuildStorage() override {computer->SetStorage("1TB SSD");}Computer* GetResult() override {return computer;}
};// 具体建造者:办公电脑
class OfficeComputerBuilder : public ComputerBuilder 
{
private:Computer* computer;public:OfficeComputerBuilder() {computer = new Computer();}~OfficeComputerBuilder() {delete computer;}void BuildCPU() override {computer->SetCPU("i3");}void BuildGPU() override {computer->SetGPU("GTX 960");}void BuildMemory() override {computer->SetMemory("8GB DDR4");}void BuildStorage() override {computer->SetStorage("512GB SSD");}Computer* GetResult() override {return computer;}
};// 指挥者:控制建造流程
class Director 
{
private:ComputerBuilder* builder = nullptr;
public:void SetBuilder(ComputerBuilder* builder) {this->builder = builder;}void Construct() {builder->BuildCPU();builder->BuildGPU();builder->BuildMemory();builder->BuildStorage();}
};// 客户端代码
int main() 
{Director director;// 创建游戏电脑GamingComputerBuilder gamingBuilder;director.SetBuilder(&gamingBuilder);director.Construct();Computer* gamingComputer = gamingBuilder.GetResult();gamingComputer->ShowSpecifications();// 创建办公电脑OfficeComputerBuilder officeBuilder;director.SetBuilder(&officeBuilder);director.Construct();Computer* officeComputer = officeBuilder.GetResult();officeComputer->ShowSpecifications();delete gamingComputer;delete officeComputer;return 0;
}

(2)总结

  • 优点:

    • 灵活应对不同需求:在这个例子中,游戏电脑和办公电脑虽然都是由CPU、GPU、内存和硬盘等部件组成,但具体的配置差别很大。通过 Director 控制构建顺序,我们可以复用建造流程,但根据不同的 具体ConcreteBuilder 实现来生成不同的产品。这使得我们在不修改整体构建逻辑的情况下,可以灵活地创建多种不同的对象。

    • 易扩展:建造者模式将复杂对象的构建过程与具体的构建实现解耦。Director 只需要知道如何控制创建流程,具体怎么创建、用什么配置并不重要。通过这种解耦,可以很容易地替换或扩展新的 ConcreteBuilder,比如还可以再实现一个 WorkstationComputerBuilder,用于构建工作站电脑。

    • 代码更加清晰:对于复杂对象的构建,通过一步步调用建造方法(如 BuildCPU()BuildMemory()),构建过程非常清晰易懂。这种模式避免了构建过程中混乱的条件判断和冗长的构造代码。

  • 缺点:

    • 增加代码复杂度:模式引入了额外的建造者、指导者等类,可能会使代码量增多,结构变复杂。
    • 多次构建成本高:如果每次构建都需要重建所有对象部分,可能导致性能开销。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1--SpringBoot外卖项目介绍及环境搭建 详解

目录 软件开发整体流程 软件开发流程 角色分工 软件环境 苍穹外卖项目介绍 项目介绍 产品原型 技术选型 开发环境搭建 前端环境搭建 后端环境搭建 完善登录功能 导入接口文档 Swagger 介绍 使用方式 常用注解 软件开发整体流程 软件开发流程 需求分析&#x…

Microsoft 365 Copilot: Wave 2 发布,开启AI时代下的全新工作流

本周一&#xff08;9月16日&#xff09;&#xff0c;微软对 Microsoft 365 Copilot 办公辅助工具进行了重大升级&#xff0c;推出 Wave 2 版本。新版 Copilot 将为 Microsoft 365 用户带来一系列新功能和改进&#xff0c;进一步提升工作效率与用户体验&#xff0c;正式开启AI时…

一个能同时to B和to C、批发零售一体化的需求分析和系统设计

一些企业纠结自己的模式是to B还是to C&#xff0c;一些企业在to B和to C中转型&#xff0c;还有一些企业在做着to B的业务&#xff0c;也在做to C的代发&#xff0c;这些企业在不停地变更着业务&#xff0c;更换着系统&#xff0c;给企业带来巨大的资金和时间成本&#xff0c;…

关于SpringBoot项目使用maven打包由于Test引起的无法正常打包问题解决

一、问题描述 在日常工作中&#xff0c;在接手项目时&#xff0c;项目未必是“正常”的&#xff0c;一般平常搭建项目&#xff0c;都不会采用一键式生成的方式&#xff0c;现在说下旧项目&#xff0c;可能项目结构并不是那么简洁&#xff0c;通常都带有与main同层级的test&…

同声传译翻译工具哪个好?不妨试试这些翻译工具

在全球化的浪潮中&#xff0c;语言沟通的重要性日益凸显&#xff0c;它不仅是跨文化交流的桥梁&#xff0c;更是连接不同文化和思想的关键。 为了跨越语言的鸿沟&#xff0c;市场上涌现了众多同声传译工具&#xff0c;它们像是科技的魔法&#xff0c;让沟通变得触手可及。 然…

Nginx实用篇:实现负载均衡、限流与动静分离

Nginx实用篇&#xff1a;实现负载均衡、限流与动静分离 | 原创作者/编辑&#xff1a;凯哥Java | 分类&#xff1a;Nginx学习系列教程 Nginx 作为一款高性能的 HTTP 服务器及反向代理解决方案&#xff0c;在互联网架构中扮演着至关重要的角色。它…

【数据结构与算法 | 灵神题单 | 二叉搜索树篇】力扣653

1. 力扣653&#xff1a;两数之和IV - 输入二叉搜索树 1.1 题目&#xff1a; 给定一个二叉搜索树 root 和一个目标结果 k&#xff0c;如果二叉搜索树中存在两个元素且它们的和等于给定的目标结果&#xff0c;则返回 true。 示例 1&#xff1a; 输入: root [5,3,6,2,4,null,7…

大数据处理技术:HBase的安装与基本操作

目录 1 实验名称 2 实验目的 3 实验内容 4 实验原理 5 实验过程或源代码 5.1 Hbase数据库的安装 5.2 创建表 5.3 添加数据、删除数据、删除表 5.4 使用Java操作HBase 6 实验结果 6.1 Hbase数据库的安装 6.2 创建表 6.3 添加数据、删除数据、删除表 6.4 使用Java操…

C++:类和对象全解

C&#xff1a;类和对象全解 一、类的定义和初始化&#xff08;一&#xff09;类的定义1、类的成员变量&#xff08;1&#xff09;成员变量&#xff08;2&#xff09;成员函数 2、实例化对象&#xff08;1&#xff09;采用普通构造函数&#xff08;2&#xff09;采用初始化列表 …

CAD的案例

在这个案例我会一步步教如何快速实现 比如我们要复刻这个图形 首先先画直线 输入L&#xff0c;然后空格&#xff0c;输入尺寸70&#xff0c;按ESC退出 到这一步画斜线&#xff0c;很简单就是直线旋转30的角度 直线教学&#xff1a; 先从右边拖到左边&#xff0c;选中这条直线…

【ShuQiHere】 探索数据挖掘的世界:从概念到应用

&#x1f310; 【ShuQiHere】 数据挖掘&#xff08;Data Mining, DM&#xff09; 是一种从大型数据集中提取有用信息的技术&#xff0c;无论是在商业分析、金融预测&#xff0c;还是医学研究中&#xff0c;数据挖掘都扮演着至关重要的角色。本文将带您深入了解数据挖掘的核心概…

中小企业体系技术抽象沉淀-异地灾备篇

IT团队内部使用工具 系列文章&#xff1a;https://blog.csdn.net/caicongyang/article/details/136857045 DDL DML管控 https://github.com/hhyo/Archery/ flyway 文档编写 wiki 技术对外输出文档推荐gitbook 同城双活数据同步方案 总览&#xff1a; vivo 系列文章&#x…

十三 系统架构设计(考点篇)

1 软件架构的概念 一个程序和计算系统软件体系结构是指系统的一个或者多个结构。结构中包括软件的构件&#xff0c;构件 的外部可见属性以及它们之间的相互关系。 体系结构并非可运行软件。确切地说&#xff0c;它是一种表达&#xff0c;使软件工程师能够&#xff1a; (1)分…

洪涝洪水滑坡灾害数据集 灾害 2300张 带标注 voc yolo

洪涝洪水滑坡灾害数据集 灾害 2300张 带标注 voc yolo 洪涝洪水滑坡灾害数据集 数据集描述 该数据集是一个专门用于检测和识别洪涝、洪水和滑坡等自然灾害的数据集&#xff0c;旨在帮助研究人员和开发者训练和评估基于深度学习的目标检测模型。数据集涵盖了两种常见的自然灾害…

8-----手机机型维修工具助手 功能较全 涵盖解锁 刷机 修复等选项 维修推荐

上图是一款功能较全的维修加密狗。目前可以无限制 任何人使用。看图片可以了解其中涵盖刷机 解锁 修复分区 查看短接图 安装驱动 修复基带等等选项。而且其中有针对各个机型型号的对应功能操作。以及一些rec5.0相关的操作选项。 通过此博文了解 ★★★★★此工具涵盖的一些…

【Java】JVM基本组成

一、JDK、JRE、JVM JDK&#xff1a;全称 “Java Development Kit” Java 开发工具包&#xff0c;提供 javac编译器、jheap、jconsole 等监控工具; JRE&#xff1a;全称 “Java Runtime Environment” Java 运行环境&#xff0c;提供 class Library 核心类库JVM; …

项目集成sharding-jdbc

目录 项目集成sharding-jdbc 1.业务分析 2.数据库构建 3.分库分表策略 项目配置默认数据源 一&#xff1a;导入sharding-jdbc依赖 二&#xff1a;在application文件中编写配置 三&#xff1a;注释掉主配置文件中配置的数据源 注意&#xff1a;这里添加了spring.main.allow…

C++之初识STL(概念)

STL&#xff08;标准模板库&#xff09; STL广义分类为&#xff1a;容器&#xff0c;算法&#xff0c;迭代器 * **容器**和**算法**之间通过**迭代器**进行无缝连接 意义&#xff1a;C的**面向对象**和**泛型编程**思想&#xff0c;目的就是**复用性的提升** STL六大组件 1. 容…

ubuntu中通过源码安装pointnet2_ops_lib

注&#xff1a;本帖所用环境为&#xff1a;ubuntu 24.04、 cuda 12.04 文章目录 1. 克隆 PointNet 源码库2. 安装依赖3. 编译 pointnet2_ops_lib4. 测试安装 1. 克隆 PointNet 源码库 首先&#xff0c;克隆 PointNet 的 GitHub 仓库&#xff1a; git clone https://github.co…

JavaEE: 深入探索TCP网络编程的奇妙世界(六)

文章目录 TCP核心机制TCP核心机制九: 面向字节流TCP核心机制十: 异常处理 小小的补充(URG 和 PSH)~TCP小结TCP/UDP 对比用UDP实现可靠传输(经典面试题) 结尾 TCP核心机制 上一篇文章JavaEE: 深入探索TCP网络编程的奇妙世界(五) 书接上文~ TCP核心机制九: 面向字节流 TCP是面…