C++ 设计模式——组合模式

news2024/11/16 13:36:22

C++ 设计模式——组合模式

    • C++ 设计模式——组合模式
      • 1. 主要组成成分
      • 2. 逐步构建透明组合模式
        • 1. 定义抽象组件(Component)
        • 2. 实现叶子组件(Leaf)
        • 3. 实现组合组件(Composite)
        • 4. 主函数(Main)
        • 透明组合模式 UML 图
          • 透明组合模式 UML 图解析
        • 透明组合模式的优点
        • 透明组合模式的缺点
        • 透明组合模式的适用场景
      • 3. 逐步构建安全组合模式
        • 1. 定义抽象组件(Component)
        • 2. 实现叶子组件(Leaf)
        • 3. 实现组合组件(Composite)
        • 4. 主函数(Main)
        • 安全组合模式 UML 图
          • 安全组合模式 UML 图解析
        • 安全组合模式的优点
        • 安全组合模式的缺点
        • 安全组合模式的适用场景
      • 总结
      • 透明组合模式完整代码
      • 安全组合模式完整代码

C++ 设计模式——组合模式

组合模式(Composite Pattern)是一种结构性设计模式,允许将一组对象组织成树形结构以表示“部分-整体”的层次结构。使得用户对单个对象和组合对象的操作/使用/处理具有一致性。组合模式使得客户端可以以统一的方式对待单个对象和组合对象,从而简化了客户端代码的复杂性。

1. 主要组成成分

  1. 抽象组件(Component):声明了叶子和组合对象的共同接口。
  2. 叶子组件(Leaf):实现了组件接口,代表树中的叶子节点。
  3. 组合组件(Composite):实现了组件接口,定义了叶子和子组件的行为,存储子组件。

2. 逐步构建透明组合模式

透明组合模式允许客户端以统一的方式处理单个对象和组合对象。通过在基类中定义 AddRemove 方法,组合对象可以自由添加和删除子对象。这种模式适用于需要处理树形结构的场景,提供了良好的灵活性和可扩展性。下面是如何逐步构建透明组合模式的示例。

1. 定义抽象组件(Component)

首先,定义一个抽象基类 FileSystem,声明所有具体组件的接口。

//抽象父类FileSystem(抽象接口)
class FileSystem
{
public:
    virtual void ShowName(int level) = 0; //显示名字,参数level用于表示显示的层级,用于显示对齐
    virtual int Add(FileSystem* pfilesys) = 0; //向当前目录中增加文件或子目录
    virtual int Remove(FileSystem* pfilesys) = 0;//从当前目录中移除文件或子目录
    virtual ~FileSystem() {} //做父类时析构函数应该为虚函数
};
2. 实现叶子组件(Leaf)

接下来,创建一个表示文件的类 File,它继承自 FileSystem

//文件相关类
class File :public FileSystem
{
public:
    //构造函数
    File(string name) :m_sname(name) {}
    //显示名字
    void ShowName(int level)
    {
        for (int i = 0; i < level; ++i) { cout << "    "; } //显示若干个空格用与对齐
        cout << "-" << m_sname << endl;
    }
    virtual int Add(FileSystem* pfilesys)
    {
        //文件中其实是不可以增加其他文件或者目录的,所以这里直接返回-1,无奈的是父类中定义了该接口,所以子类中也必须实现该接口
        return -1;
    }
    virtual int Remove(FileSystem* pfilesys)
    {
        //文件中不包含其他文件或者目录,所以这里直接返回-1
        return -1;
    }
private:
    string m_sname;  //文件名
};
3. 实现组合组件(Composite)

接着,创建一个表示目录的类 Dir,它也继承自 FileSystem

//目录相关类
class Dir :public FileSystem
{
public:
    //构造函数
    Dir(string name) :m_sname(name) {}
    //显示名字
    void ShowName(int level)
    {
        //(1)显示若干个空格用与对齐
        for (int i = 0; i < level; ++i) { cout << "    "; }
        //(2)输出本目录名
        cout << "+" << m_sname << endl;
        //(3)显示的层级向下走一级
        level++;
        //(4)输出所包含的子内容(可能是文件,也可能是子目录)
        //遍历目录中的文件和子目录
        for (auto iter = m_child.begin(); iter != m_child.end(); ++iter)
        {
            (*iter)->ShowName(level);
        }//end for
    }
    virtual int Add(FileSystem* pfilesys)
    {
        m_child.push_back(pfilesys);
        return 0;
    }
    virtual int Remove(FileSystem* pfilesys)
    {
        m_child.remove(pfilesys);
        return 0;
    }
private:
    string m_sname;             //文件名
    list<FileSystem*> m_child;  //目录中包含的文件或其他目录列表
};

4. 主函数(Main)

main 函数中,创建文件和目录对象,并构建树形结构。

int main()
{
    Dir* root = new Dir("root");
    FileSystem* file1 = new File("common.mk");
    FileSystem* file2 = new File("config.mk");
    Dir* appDir = new Dir("app");
    FileSystem* file3 = new File("nginx.c");

    // 构建树形结构
    root->Add(file1);
    root->Add(file2);
    root->Add(appDir);
    appDir->Add(file3);

    // 显示整个目录结构
    root->ShowName(0);

    // 释放资源
    delete file3;
    delete appDir;
    delete file2;
    delete file1;
    delete root;

    return 0;
}

运行上述代码,输出结果如下:

+root
    -common.mk
    -config.mk
    +app
        -nginx.c
透明组合模式 UML 图

透明组合模式 UML 图

透明组合模式 UML 图解析
  • Component (抽象组件): 为树枝和树叶定义接口(例如,增加、删除、获取子节点等),可以是抽象类,包含所有子类公共行为的声明或默认实现体。这里指 FileSystem 类。
  • Leaf (叶子组件): 用于表示树叶节点对象,这种对象没有子节点,因此抽象组件中定义的一些接口(例如 AddRemove)在这里没有实现的意义。这里指 File 类。
  • Composite (树枝组件): 用于表示一个容器(树枝)节点对象,可以包含子节点,子节点可以是树叶,也可以是树枝,其中提供了一个集合用于存储子节点(以此形成一个树形结构,可以通过递归来访问所有节点)。实现了抽象组件中定义的接口。这里指 Dir 类。
透明组合模式的优点
  • 一致的接口:客户端可以使用相同的方式处理单个对象和组合对象。
  • 简化代码:减少了客户端代码的复杂性,便于管理和扩展。
  • 灵活性:可以轻松地添加新的叶子或组合类。
透明组合模式的缺点
  • 设计复杂性:需要设计一个抽象组件接口,可能导致过多的类。
  • 性能开销:在某些实现中,可能会有额外的性能开销,特别是在树结构较深时。
透明组合模式的适用场景
  • 需要表示“部分-整体”层次结构的场景,例如文件系统、组织结构等。
  • 客户端需要统一处理单个对象和组合对象的场景。

3. 逐步构建安全组合模式

安全组合模式通过类型安全的方式管理树形结构中的对象,确保只有组合对象可以添加子对象。通过实现 ifCompositeObj 方法,能够明确区分叶子和组合对象,从而避免不当操作。此模式适用于需要严格管理树形结构的场景。以下是逐步构建安全组合模式的示例。

1. 定义抽象组件(Component)

首先,定义一个抽象基类 FileSystem,它声明了所有具体组件的接口。

#include <iostream>
#include <list>
#include <string>

class Dir; // 前向声明

//抽象父类FileSystem(抽象接口)
class FileSystem
{
public:
    virtual void ShowName(int level) = 0; //显示名字,参数level用于表示显示的层级,用于显示对齐
    virtual ~FileSystem() {}//做父类时析构函数应该为虚函数
    virtual Dir* ifCompositeObj() { return nullptr; }
    virtual int countNumOfFiles() = 0;  //统计目录下包含的文件个数

};
2. 实现叶子组件(Leaf)

接下来,创建一个表示文件的类 File,它继承自 FileSystem

//文件相关类
class File :public FileSystem
{
public:
    //构造函数
    File(string name) :m_sname(name) {}

    //显示名字
    void ShowName(int level)
    {
        for (int i = 0; i < level; ++i) { cout << "    "; } //显示若干个空格用与对齐
        cout << "-" << m_sname << endl;
    }
    
    virtual int countNumOfFiles()
    {
        return 1; //文件节点,做数量统计时按1计算
    }

private:
    string m_sname;  //文件名
};
3. 实现组合组件(Composite)

接着,创建一个表示目录的类 Dir,它也继承自 FileSystem

// 目录类
class Dir :public FileSystem
{
    //该类内容基本没变,把Add和Remove成员函数前面的virtual修饰符去掉即可。
public:
    //构造函数
    Dir(string name) :m_sname(name) {}
    //显示名字
    void ShowName(int level)
    {
        //(1)显示若干个空格用与对齐
        for (int i = 0; i < level; ++i) { cout << "    "; }
        //(2)输出本目录名
        cout << "+" << m_sname << endl;
        //(3)显示的层级向下走一级
        level++;
        //(4)输出所包含的子内容(可能是文件,也可能是子目录)
        //遍历目录中的文件和子目录
        for (auto iter = m_child.begin(); iter != m_child.end(); ++iter)
        {
            (*iter)->ShowName(level);
        }//end for
    }
    /*virtual*/ int Add(FileSystem* pfilesys)
    {
        m_child.push_back(pfilesys);
        return 0;
    }
    /*virtual*/ int Remove(FileSystem* pfilesys)
    {
        m_child.remove(pfilesys);
        return 0;
    }

    virtual Dir* ifCompositeObj() { return this; }

    virtual int countNumOfFiles()
    {
        int iNumOfFiles = 0;
        for (auto iter = m_child.begin(); iter != m_child.end(); ++iter)
        {
            iNumOfFiles += (*iter)->countNumOfFiles();//递归调用
        }
        return iNumOfFiles;
    }


private:
    string m_sname;             //文件名
    list<FileSystem*> m_child;  //目录中包含的文件或其他目录列表
};
4. 主函数(Main)

main 函数中,创建文件和目录对象,并构建树形结构。

int main() {
    Dir* root = new Dir("root");
    FileSystem* file1 = new File("common.mk");
    FileSystem* file2 = new File("config.mk");
    Dir* appDir = new Dir("app");
    FileSystem* file3 = new File("nginx.c");

    // 构建树形结构
    root->Add(file1);
    root->Add(file2);
    root->Add(appDir);
    appDir->Add(file3);

    // 显示整个目录结构
    root->ShowName(0);
    std::cout << "文件的数量为:" << root->countNumOfFiles() << std::endl;

    // 释放资源
    delete file3;
    delete appDir;
    delete file2;
    delete file1;
    delete root;

    return 0;
}

运行上述代码,输出结果如下:

+root
    -common.mk
    -config.mk
    +app
        -nginx.c
文件的数量为:3
安全组合模式 UML 图

安全组合模式 UML 图

安全组合模式 UML 图解析
  • Component (抽象组件): 定义树枝和树叶的接口,包含公共行为的声明。
  • Leaf (叶子组件): 表示没有子节点的对象,通常不实现 AddRemove 方法。
  • Composite (树枝组件): 包含子节点,能够递归地调用子节点的方法。
安全组合模式的优点
  • 类型安全:通过类型检查,确保只有组合对象可以添加子对象。
  • 清晰的责任分配:各类的功能分离更加明确,便于维护。
安全组合模式的缺点
  • 复杂性增加:实现安全组合模式可能需要更多的代码和逻辑。
  • 不够灵活:如果需要动态改变对象的行为,可能会受到限制。
安全组合模式的适用场景
  • 需要确保组合对象的类型安全,避免非法操作的场景。
  • 需要明确区分叶子和组合对象的场景。

总结

组合模式是一种强大的设计模式,适用于处理树形结构的场景。通过透明组合模式和安全组合模式,两者各有优缺点,开发者应根据具体需求选择合适的实现方式。组合模式不仅简化了客户端的代码,还提高了代码的可扩展性和可维护性。

透明组合模式完整代码

#include <iostream>
#include <list>
using namespace std;

//抽象父类FileSystem(抽象接口)
class FileSystem
{
public:
    virtual void ShowName(int level) = 0; //显示名字,参数level用于表示显示的层级,用于显示对齐
    virtual int Add(FileSystem* pfilesys) = 0; //向当前目录中增加文件或子目录
    virtual int Remove(FileSystem* pfilesys) = 0;//从当前目录中移除文件或子目录
    virtual ~FileSystem() {} //做父类时析构函数应该为虚函数
};

//文件相关类
class File :public FileSystem
{
public:
    //构造函数
    File(string name) :m_sname(name) {}
    //显示名字
    void ShowName(int level)
    {
        for (int i = 0; i < level; ++i) { cout << "    "; } //显示若干个空格用与对齐
        cout << "-" << m_sname << endl;
    }
    virtual int Add(FileSystem* pfilesys)
    {
        //文件中其实是不可以增加其他文件或者目录的,所以这里直接返回-1,无奈的是父类中定义了该接口,所以子类中也必须实现该接口
        return -1;
    }
    virtual int Remove(FileSystem* pfilesys)
    {
        //文件中不包含其他文件或者目录,所以这里直接返回-1
        return -1;
    }
private:
    string m_sname;  //文件名
};

//目录相关类
class Dir :public FileSystem
{
public:
    //构造函数
    Dir(string name) :m_sname(name) {}
    //显示名字
    void ShowName(int level)
    {
        //(1)显示若干个空格用与对齐
        for (int i = 0; i < level; ++i) { cout << "    "; }
        //(2)输出本目录名
        cout << "+" << m_sname << endl;
        //(3)显示的层级向下走一级
        level++;
        //(4)输出所包含的子内容(可能是文件,也可能是子目录)
        //遍历目录中的文件和子目录
        for (auto iter = m_child.begin(); iter != m_child.end(); ++iter)
        {
            (*iter)->ShowName(level);
        }//end for
    }
    virtual int Add(FileSystem* pfilesys)
    {
        m_child.push_back(pfilesys);
        return 0;
    }
    virtual int Remove(FileSystem* pfilesys)
    {
        m_child.remove(pfilesys);
        return 0;
    }
private:
    string m_sname;             //文件名
    list<FileSystem*> m_child;  //目录中包含的文件或其他目录列表
};

int main()
{
    //(1)创建各种目录,文件对象
    FileSystem* pdir1 = new Dir("root");
    //-------
    FileSystem* pfile1 = new File("common.mk");
    FileSystem* pfile2 = new File("config.mk");
    FileSystem* pfile3 = new File("makefile");
    //-------
    FileSystem* pdir2 = new Dir("app");
    FileSystem* pfile4 = new File("nginx.c");
    FileSystem* pfile5 = new File("ngx_conf.c");
    //-------
    FileSystem* pdir3 = new Dir("signal");
    FileSystem* pfile6 = new File("ngx_signal.c");
    //-------
    FileSystem* pdir4 = new Dir("_include");
    FileSystem* pfile7 = new File("ngx_func.h");
    FileSystem* pfile8 = new File("ngx_signal.h");

    //(2)构造树形目录结构
    pdir1->Add(pfile1);
    pdir1->Add(pfile2);
    pdir1->Add(pfile3);
    //-------
    pdir1->Add(pdir2);
    pdir2->Add(pfile4);
    pdir2->Add(pfile5);
    //-------
    pdir1->Add(pdir3);
    pdir3->Add(pfile6);
    //-------
    pdir1->Add(pdir4);
    pdir4->Add(pfile7);
    pdir4->Add(pfile8);

    //(3)输出整个目录结构,只要调用根目录的ShowName方法即可,每个子目录都有自己的ShowName方法负责自己旗下的文件和目录的显示
    pdir1->ShowName(0);

    //(4)释放资源
    delete pfile8;
    delete pfile7;
    delete pdir4;
    //-------
    delete pfile6;
    delete pdir3;
    //-------
    delete pfile5;
    delete pfile4;
    delete pdir2;
    //-------
    delete pfile3;
    delete pfile2;
    delete pfile1;
    delete pdir1;
    return 0;
}

安全组合模式完整代码

#include <iostream>
#include <list>
using namespace std;

class Dir;
//抽象父类FileSystem(抽象接口)
class FileSystem
{
public:
    virtual void ShowName(int level) = 0; //显示名字,参数level用于表示显示的层级,用于显示对齐
    virtual ~FileSystem() {}//做父类时析构函数应该为虚函数

public:
    virtual Dir* ifCompositeObj() { return nullptr; }

public:
    virtual int countNumOfFiles() = 0;  //统计目录下包含的文件个数

};

//文件相关类
class File :public FileSystem
{
public:
    //构造函数
    File(string name) :m_sname(name) {}

    //显示名字
    void ShowName(int level)
    {
        for (int i = 0; i < level; ++i) { cout << "    "; } //显示若干个空格用与对齐
        cout << "-" << m_sname << endl;
    }

public:
    virtual int countNumOfFiles()
    {
        return 1; //文件节点,做数量统计时按1计算
    }

private:
    string m_sname;  //文件名
};

class Dir :public FileSystem
{
    //该类内容基本没变,把Add和Remove成员函数前面的virtual修饰符去掉即可。
public:
    //构造函数
    Dir(string name) :m_sname(name) {}
    //显示名字
    void ShowName(int level)
    {
        //(1)显示若干个空格用与对齐
        for (int i = 0; i < level; ++i) { cout << "    "; }
        //(2)输出本目录名
        cout << "+" << m_sname << endl;
        //(3)显示的层级向下走一级
        level++;
        //(4)输出所包含的子内容(可能是文件,也可能是子目录)
        //遍历目录中的文件和子目录
        for (auto iter = m_child.begin(); iter != m_child.end(); ++iter)
        {
            (*iter)->ShowName(level);
        }//end for
    }
    /*virtual*/ int Add(FileSystem* pfilesys)
    {
        m_child.push_back(pfilesys);
        return 0;
    }
    /*virtual*/ int Remove(FileSystem* pfilesys)
    {
        m_child.remove(pfilesys);
        return 0;
    }

public:
    virtual Dir* ifCompositeObj() { return this; }

public:
    virtual int countNumOfFiles()
    {
        int iNumOfFiles = 0;
        for (auto iter = m_child.begin(); iter != m_child.end(); ++iter)
        {
            iNumOfFiles += (*iter)->countNumOfFiles();//递归调用
        }
        return iNumOfFiles;
    }


private:
    string m_sname;             //文件名
    list<FileSystem*> m_child;  //目录中包含的文件或其他目录列表
};

int main()
{
    //(1)创建各种目录,文件对象
    Dir* pdir1 = new Dir("root");
    //-------
    FileSystem* pfile1 = new File("common.mk");
    FileSystem* pfile2 = new File("config.mk");
    FileSystem* pfile3 = new File("makefile");
    //-------
    Dir* pdir2 = new Dir("app");
    if (pdir2->ifCompositeObj() != nullptr)
    {
        //是个组合对象,可以向其中增加单个对象和其它组合对象
    }
    if (dynamic_cast<Dir*>(pdir2) != nullptr)
    {
        //是个组合对象,可以向其中增加单个对象和其它组合对象
    }

    FileSystem* pfile4 = new File("nginx.c");
    FileSystem* pfile5 = new File("ngx_conf.c");
    //-------
    Dir* pdir3 = new Dir("signal");
    FileSystem* pfile6 = new File("ngx_signal.c");
    //-------
    Dir* pdir4 = new Dir("_include");
    FileSystem* pfile7 = new File("ngx_func.h");
    FileSystem* pfile8 = new File("ngx_signal.h");

    //(2)构造树形目录结构
    //这部分内容基本没变,
    pdir1->Add(pfile1);
    pdir1->Add(pfile2);
    pdir1->Add(pfile3);
    //-------
    pdir1->Add(pdir2);
    pdir2->Add(pfile4);
    pdir2->Add(pfile5);
    //-------
    pdir1->Add(pdir3);
    pdir3->Add(pfile6);
    //-------
    pdir1->Add(pdir4);
    pdir4->Add(pfile7);
    pdir4->Add(pfile8);

    //(3)输出整个目录结构,只要调用根目录的ShowName方法即可,每个子目录都有自己的ShowName方法负责自己旗下的文件和目录的显示
    pdir1->ShowName(0);

    cout << "文件的数量为:" << pdir1->countNumOfFiles() << endl;

    //(4)释放资源
    //这部分内容基本没变,
    delete pfile8;
    delete pfile7;
    delete pdir4;
    //-------
    delete pfile6;
    delete pdir3;
    //-------
    delete pfile5;
    delete pfile4;
    delete pdir2;
    //-------
    delete pfile3;
    delete pfile2;
    delete pfile1;
    delete pdir1;

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nacos踩坑

最近遇到项目部署&#xff0c;遇到Nacos中的配置读取不到&#xff0c;导致服务起不来。服务器银河麒麟x86&#xff0c;Nacos版本2.3.2, openJdk8u43 报错如下&#xff1a; java.lang.UnsatisfiedLinkError: no com_alibaba_nacos_shaded_io_grpc_netty_shaded_netty_transport…

Linux磁盘操作之du命令

使用du命令&#xff0c;您可以查看指定目录或文件的磁盘使用量总计。这对于了解特定目录或文件占用的磁盘空间大小非常有用&#xff0c;可以帮助您进行磁盘空间管理和清理。 参数说明 du是一个用于显示目录或文件的磁盘使用情况的命令&#xff0c;du是disk usage的缩写&#…

从图像到视频:Web Codecs API编码技术解析

初探Web Codecs API 三 前言 在之前的文章中,咱们简单的介绍了解码相关的东西,这一节咱们来简单聊聊编码相关的东西。 编码的目的就是为了压缩,去除空间、时间维度的冗余。 这里又不得不提起前面所说的I 帧、P 帧、B 帧和 IDR 帧。 众所周知,视频是连续的图像序列,由…

【添加核心机械臂动力学】Model and Control a Manipulator Arm with Robotics and Simscape

机械臂动力学 为了设计控制器&#xff0c;机械臂动力学必须表示给定力矩输入的关节位置。这在机械臂动力学子系统中通过一个前向动力学块实现&#xff0c;该块将关节力矩转换为给定当前状态的关节加速度&#xff0c;然后通过两次积分得到完整的关节配置。积分器初始化为q0和dq…

自闭症托管托养机构:星贝育园的优势与使命

在当今社会&#xff0c;自闭症儿童作为一群需要特别关注和照顾的群体&#xff0c;其教育与康复问题日益受到社会各界的重视。自闭症托管托养机构作为这一领域的重要力量&#xff0c;承担着为自闭症儿童提供全方位、个性化支持的重任。星贝育园&#xff0c;作为一所全日寄宿制的…

使用libsvm时遇到MATLAB has encountered an internal problem and needs to close

最近在MATLAB中使用libsvm跑别人的程序&#xff0c;该程序在大部分数据集上可以正常运行&#xff0c;但在有一个数据集上运行时MATLAB会报“MATLAB has encountered an internal problem and needs to close”的错误&#xff1a; 凭直觉猜应该是数据集有啥问题&#xff0c;但又…

AI人的列表!《中国人工智能学会推荐国际学术会议和国际/国内期刊目录》正式发布

在全球科技迅猛发展的今天&#xff0c;人工智能&#xff08;AI&#xff09;已成为推动社会进步的关键力量。为了更好地指导AI领域的科研方向&#xff0c;加强学术交流&#xff0c;促进学术成果的创新与应用&#xff0c;中国人工智能学会&#xff08;CAAI&#xff09;在2024年8月…

数据分析案例-2024年裁员数据集可视化分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

XFTP软件的使用 ---- 远程上传、下载文件

本文假设你的电脑里面已经有XFTP软件。 一、简介 是一个基于 windows 平台的功能强大的SFTP、FTP文件传输软件。通过Xftp软件&#xff0c;windows 用户能安全地在UNIX/Linux 和 Windows PC 之间传输文件。 二、 使用方法【步骤】 打开软件&#xff0c;得到如下图界面。 首先我…

STL--unordered_set和unordered_map的模拟实现

1.unordered系列关联式容器 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到&#xff0c;即最差情况下需要比较红黑树的高度次&#xff0c;当树中的节点非常多时&#xff0c;查询效率也不理想。最好的查询是&#xff0c;进行很…

如何使用ssm实现基于java斗车交易系统设计与实现+vue

TOC ssm082基于java斗车交易系统设计与实现vue 系统概述 1.1 概述 随着社会的快速发展&#xff0c;计算机的影响是全面且深入的。人们的生活水平不断提高&#xff0c;日常生活中人们对斗车交易方面的要求也在不断提高&#xff0c;需要咨询的人数更是不断增加&#xff0c;使得…

OpenCV 图像处理基础算法介绍c++

VS2022配置OpenCV环境 关于OpenCV在VS2022上配置的教程可以参考&#xff1a;VS2022 配置OpenCV开发环境详细教程 图像处理 图像处理是一个广泛的领域&#xff0c;它涉及到对图像数据进行分析、修改和改进的各种技术。以下是一些基本的图像处理操作&#xff0c;这些操作通常可…

模型 蒂蒙斯创业过程

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。机会、团队、资源&#xff1a;创业成功的三角。 1 蒂蒙斯创业过程的应用 1.1 京东&#xff1a;蒂蒙斯模型下创业成功的典范 京东是中国知名的电子商务平台&#xff0c;其早期发展阶段充分体现了蒂蒙…

接口基础知识12:cookie、session和token

​课程大纲 ‌Cookie、Session和Token是Web应用中常用的身份验证和会话管理机制&#xff0c;各有特点&#xff0c;适用于不同的应用场景。 一、Cookie 1.1 什么是Cookie Cookie是存储在客户端浏览器中的小段数据&#xff0c;通常用于存储用户偏好设置或用于跟踪用户活动。 C…

51单片机——数码管控制

1、数码管介绍 LED数码管&#xff1a;数码管是一种简单、廉价的显示器&#xff0c;是由多个发光二极管封装在一起组成“8”字型的器件。 2、数码管驱动方式 单片机直接扫描&#xff1a;硬件设备简单&#xff0c;但会耗费大量的单片机CPU时间 专用驱动芯片&#xff1a;内部自…

8月24日笔记

ew的使用 EW&#xff08;EarthWorm&#xff09;是一套基于C语言开发的轻量级且功能强大的网络穿透工具&#xff0c;它支持Socks5代理、端口转发及端口映射等功能&#xff0c;能够在复杂的网络环境中实现高效稳定的网络穿透。这款全平台适用的工具&#xff08;包括Windows、Lin…

proc文件的写操作机制

“一切皆是文件”。 Linux的基本哲学之一。它是指linux系统中的所有一切都可以通过文件的方式访问、管理&#xff0c;即便不是文件&#xff0c;也以文件的形式来管理。例如硬件设备、进程、套接字等都抽象成文件&#xff0c;使用统一的用户接口&#xff0c;虽然文件类型各不相同…

ComfyUI IPAdapter plus的模型应该怎么装-免费版-2024.8.25

&#x1f386;背景 ipadapter相关的节点大家应该都不陌生&#xff0c;具体是做什么的就不详细介绍了&#xff0c;但是还是有很多新入门的朋友不太了解这个节点相关的这一堆模型到底应该怎么安装。这里就借着官方节点的介绍来大概讲下这个话题。 涉及到的节点源地址&#xff1…

大数据技术之Zookeeper安装 (2)

目录 下载地址 本地模式安装 1&#xff09;安装前准备 2&#xff09;配置修改 3&#xff09;操作 Zookeeper 配置参数解读 Zookeeper 集群操作 集群规划 解压安装 配置服务器编号 配置 zoo.cfg 文件 集群操作 Zookeeper 集群启动停止脚本 创建脚本 增加脚本执行权限 …

宠物毛发会携带病菌源吗?宠物店空气净化器使体验分享

近期&#xff0c;我接诊了一位肺结节患者&#xff0c;他的第一反应便是联想到家中的猫咪。这种担忧并非毫无根据&#xff0c;过敏体质的人群&#xff0c;无论是对毛发还是排泄物敏感&#xff0c;养宠物都会增加患结节的风险。即便不存在过敏问题&#xff0c;宠物毛发作为病菌的…