创建型设计模式(C++)

news2024/10/2 8:42:59

文章目录

  • 1.简单工厂模式&静态工厂模式
  • 2.工厂方法模式
  • 3.抽象工厂模式
  • 4.原型模式
  • 5.单例模式
    • a.饿汉式
    • b.懒汉式
  • 6.建造者模式(生成器模式)

在这里插入图片描述

创建型模式提供了创建对象的机制,旨在提升已有代码的灵活性可复用性

部分插图来自: https://refactoringguru.cn/design-patterns/catalog

1.简单工厂模式&静态工厂模式

简单工厂模式严格来说并不是一种设计模式,而更像是一种编程习惯。简单工厂模式在创建对象时不会对客户端暴露创建逻辑,而是通过使用一个共同的接口来提供新创建的对象。当这个提供对象接口被定义为静态方法时,简单工厂模式也被称为静态工厂模式


简单工厂模式包含如下角色:

  • 抽象产品:定义产品规范,描述产品主要特性和功能,是所有具体产品的基类。
  • 具体产品:实现或者继承抽象产品。
  • 具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品。

简单工厂模式优点:

  1. 封装了创建对象的过程,当一个调用者想创建一个对象时只需要知道其名称就可以了。
  2. 对象创建和业务逻辑被分开,如果要添加新产品只需要修改工厂类,而不需要在原代码中修改。降低了客户代码修改的可能性,在一定程度上增加了代码的可扩展性。

简单工厂模式缺点:增加新产品时需要修改工厂类的代码,违背了开闭原则(对扩展开放,对修改封闭)。

#include <iostream>

/* 猫基类 */
class Cat {
public:
    virtual void bark() = 0;

    virtual ~Cat() = default;
};

/* 狸花猫 */
class DragonLi : public Cat {
public:
    void bark() override {
        std::cout << "DragonLi: meow~" << std::endl;
    }
};

/* 缅因猫 */
class MaineCoon : public Cat {
public:
    void bark() override {
        std::cout << "MaineCoon: meow~" << std::endl;
    }
};

/* 布偶猫 */
class Ragdoll : public Cat {
public:
    void bark() override {
        std::cout << "Ragdoll: meow~" << std::endl;
    }
};

/* 静态工厂类 专门用来生产猫咪 */
class SimpleCatFactory {
public:
    static Cat *CreateCat(const std::string &category) {
        if (category == "DragonLi") {
            return new DragonLi();
        } else if (category == "MaineCoon") {
            return new MaineCoon();
        } else {
            return new Ragdoll();
        }
    }
};

int main() {
    Cat *dragonLi = SimpleCatFactory::CreateCat("DragonLi");
    dragonLi->bark();

    Cat *maineCoon = SimpleCatFactory::CreateCat("MaineCoon");
    maineCoon->bark();

    Cat *ragdoll = SimpleCatFactory::CreateCat("Ragdoll");
    ragdoll->bark();

    delete dragonLi;
    delete maineCoon;
    delete ragdoll;

    return 0;
}

atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main 
DragonLi: meow~
MaineCoon: meow~
Ragdoll: meow~
atreus@MacBook-Pro % 

2.工厂方法模式

工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法接口允许子类决定所要实例化对象的类型。工厂方法模式使一个产品类的实例化延迟到工厂的子类中进行。

在这里插入图片描述


工厂方法模式包含如下角色:

  • 抽象产品:定义产品规范,描述产品主要特性和功能,是所有具体产品的基类。
  • 具体产品:实现或者继承抽象产品,由具体工厂来创建,与具体工厂之间一一对应。
  • 抽象工厂:提供了创建产品的接口,调用者通用它访问具体工厂的工厂方法来创建产品。
  • 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。

工厂方法模式优点:

  1. 用户只需要知道具体工厂的名称就可以得到想要的产品,而无需知道产品的具体创建过程,从而避免了用户和具体产品之间的紧密耦合
  2. 可以将产品创建代码放在程序的单一位置,从而使得代码更容易维护,满足单一职责原则
  3. 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则

工厂方法模式缺点:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,增加了系统的复杂度

#include <iostream>

/* 猫基类 */
class Cat {
public:
    virtual void bark() = 0;

    virtual ~Cat() = default;
};

/* 狸花猫 */
class DragonLi : public Cat {
public:
    void bark() override {
        std::cout << "DragonLi: meow~" << std::endl;
    }
};

/* 缅因猫 */
class MaineCoon : public Cat {
public:
    void bark() override {
        std::cout << "MaineCoon: meow~" << std::endl;
    }
};

/* 抽象工厂类 */
class CatFactory {
public:
    virtual Cat *CreateCat() = 0;

    virtual ~CatFactory() = default;
};

class DragonLiFactory : public CatFactory {
public:
    Cat *CreateCat() override {
        return new DragonLi();
    }
};

class MaineCoonFactory : public CatFactory {
public:
    Cat *CreateCat() override {
        return new MaineCoon();
    }
};

int main() {
    CatFactory *dragonLiFactory = new DragonLiFactory();
    Cat *dragonLi = dragonLiFactory->CreateCat();
    dragonLi->bark();
    delete dragonLi;
    delete dragonLiFactory;

    CatFactory *maineCoonFactory = new MaineCoonFactory();
    Cat *maineCoon = maineCoonFactory->CreateCat();
    maineCoon->bark();
    delete maineCoon;
    delete maineCoonFactory;

    return 0;
}

atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main                             
DragonLi: meow~
MaineCoon: meow~
atreus@MacBook-Pro % 

3.抽象工厂模式

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产某个单一的产品,而抽象工厂模式可生产一系列相关的产品

在这里插入图片描述


抽象工厂模式包含如下角色:

  • 抽象产品:定义产品规范,描述产品主要特性和功能,是所有具体产品的基类。
  • 具体产品:实现或者继承抽象产品,由具体工厂来创建,与具体工厂之间是多对一的关系。
  • 抽象工厂:提供了创建产品的接口,调用者通用它访问具体工厂的工厂方法来创建一系列相关的产品。
  • 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。

抽象工厂方法模式优点:

  1. 可以确保同一工厂生成的产品相互匹配,比如下例中的美国工厂不会生产出日本战舰。
  2. 可以避免客户端和具体产品代码的耦合
  3. 基于工厂方法模式改进,同样满足单一职责原则开闭原则

抽象工厂方法模式缺点:代码较为复杂,当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。比如我们在下面代码中添加一个有关驱逐舰的方法,包括抽象工厂在内的工厂类都需要进行修改。

#include <iostream>

/* 战列舰基类 */
class Battleship {
public:
    virtual void fire() = 0;

    virtual ~Battleship() = default;
};

/* 巡洋舰基类 */
class Cruiser {
public:
    virtual void fire() = 0;

    virtual ~Cruiser() = default;
};

/* 抽象工厂类 */
class AbstractFactory {
public:
    virtual Battleship *createBattleship() = 0;

    virtual Cruiser *createCruiser() = 0;

    virtual ~AbstractFactory() = default;
};

/* 衣阿华级战列舰 美国 */
class Iowa : public Battleship {
public:
    void fire() override {
        std::cout << "Iowa: fire!" << std::endl;
    }
};

/* 得梅因级巡洋舰 美国 */
class DesMoines : public Cruiser {
public:
    void fire() override {
        std::cout << "DesMoines: fire!" << std::endl;
    }
};

/* 大和级战列舰 日本 */
class Yamato : public Battleship {
public:
    void fire() override {
        std::cout << "Yamato: fire!" << std::endl;
    }
};

/* 伊吹级巡洋舰 日本 */
class Ibuki : public Cruiser {
public:
    void fire() override {
        std::cout << "Ibuki: fire!" << std::endl;
    }
};

/* 美国工厂类 */
class AmericanFactory : public AbstractFactory {
public:
    Battleship *createBattleship() override {
        return new Iowa;
    }

    Cruiser *createCruiser() override {
        return new DesMoines;
    }
};

/* 日本工厂类 */
class JapaneseFactory : public AbstractFactory {
public:
    Battleship *createBattleship() override {
        return new Yamato;
    }

    Cruiser *createCruiser() override {
        return new Ibuki;
    }
};

int main() {
    AbstractFactory *americanFactory = new AmericanFactory;
    Battleship *iowa = americanFactory->createBattleship();
    iowa->fire();
    delete iowa;
    delete americanFactory;

    AbstractFactory *japaneseFactory = new JapaneseFactory;
    Cruiser *ibuki = japaneseFactory->createCruiser();
    ibuki->fire();
    delete ibuki;
    delete japaneseFactory;

    return 0;
}

atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main                             
Iowa: fire!
Ibuki: fire!
atreus@MacBook-Pro % 

4.原型模式

原型模式是一种创建型设计模式, 它用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象, 而又无需使代码依赖它们所属的类(依赖实例化后的对象,不依赖类定义)。

在这里插入图片描述


原型模式包含如下角色:

  • 抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。
  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

原型模式优点:

  1. 可以轻松克隆复杂对象,且无需与它们所属的具体类相耦合。
  2. 可以克隆预生成原型,避免反复运行初始化代码。

原型模式缺点:克隆包含循环引用的复杂对象可能会非常麻烦。

#include <iostream>

/* 抽象原型类 */
class Prototype {
public:
    virtual Prototype *clone() = 0;

    virtual ~Prototype() = default;
};

/* 猫咪类 */
class Cat : public Prototype {
public:
    Cat() = default;

    /* 深拷贝 */
    Cat *clone() override {
        return new Cat();
    }

    /* 浅拷贝 */
    // Cat *clone() override {
    //    return this;
    // }
};

int main() {
    Cat *oldCat = new Cat();
    Cat *newCat = oldCat->clone();

    std::cout << oldCat << std::endl;
    std::cout << newCat << std::endl;

    delete oldCat;
    delete newCat;

    return 0;
}

atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main 
0x60000321c040
0x60000321c050
atreus@MacBook-Pro % 

5.单例模式

单例模式只涉及到一个单一的类,该类让你能够保证一个类只有一个实例,并提供一个访问该实例的全局节点。

在这里插入图片描述


单例模式包含如下角色:

  • 单例类:创建并维持一个唯一实例的类;
  • 访问类:使用单例类。

单例模式优点:

  1. 保证一个类只有一个实例,这对于线程池和连接池等池化对象很有意义。
  2. 仅需要在首次请求单例对象时对其进行初始化。

单例模式缺点:

  1. 单例模式同时解决了保证一个类只有一个实例为该实例提供一个全局访问节点两个问题, 所以违反了单一职责原则
  2. 该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。

单例设计模式分为两种:

  • 饿汉式:类加载时就会创建该单实例对象。缺点是单例创建后不一定会立即被使用,会造成一定的内存浪费
  • 懒汉式:单实例对象不会在类加载时被创建,而是在首次使用该对象时创建。缺点是在多线程情况下需要着重考虑线程安全问题。

a.饿汉式

#include <iostream>

/* 通过静态变量实现的单例类 */
class Cat {
private:
    /* 让构造函数私有以避免类被实例化 */
    Cat() = default;

    /* 类对应的唯一的对象 */
    static Cat *m_instance;

public:
    /* 实例对象的唯一访问方式 */
    static Cat *getInstance() {
        return m_instance;
    }
};

/* 静态成员变量需要类内定义类外初始化 */
Cat *Cat::m_instance = new Cat;

int main() {
    Cat *dragonLi = Cat::getInstance();
    Cat *ragdoll = Cat::getInstance();

    std::cout << dragonLi << std::endl;
    std::cout << ragdoll << std::endl;

    delete dragonLi;
    delete ragdoll; // 由于两个猫咪实际上是一个单例 所以会发成内存的重复释放

    return 0;
}

atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main                             
0x6000007dc040
0x6000007dc040
main(86372,0x1f801c140) malloc: *** error for object 0x6000007dc040: pointer being freed was not allocated
main(86372,0x1f801c140) malloc: *** set a breakpoint in malloc_error_break to debug
zsh: abort      ./main
atreus@MacBook-Pro % 

b.懒汉式

#include <iostream>

/* 通过静态变量实现的单例类 */
class Cat {
private:
    /* 类对应的唯一的对象 */
    static Cat *instance;

    /* 让构造函数私有以避免类被实例化 */
    Cat() = default;

public:
    /* 实例对象的唯一访问方式 */
    static Cat *getInstance() {
    	// 多线程场景下此处需要加锁
        instance = (instance == nullptr) ? new Cat : instance;
        return instance;
    }
};

/* 静态成员变量需要类内定义类外初始化 */
Cat *Cat::instance = nullptr;

int main() {
    Cat *dragonLi = Cat::getInstance();
    Cat *ragdoll = Cat::getInstance();

    std::cout << dragonLi << std::endl;
    std::cout << ragdoll << std::endl;

    delete dragonLi;
    delete ragdoll; // 由于两个猫咪实际上是一个单例 所以会发成内存的重复释放

    return 0;
}

atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main                             
0x600003c18040
0x600003c18040
main(75509,0x1f801c140) malloc: *** error for object 0x600003c18040: pointer being freed was not allocated
main(75509,0x1f801c140) malloc: *** set a breakpoint in malloc_error_break to debug
zsh: abort      ./main
atreus@MacBook-Pro % 

通常,为了避免上述类似的对同一单例的多次释放,可以将单例模式与 RAII 机制结合使用:

/* 以 RAII 方式来控制单例 */
class CatStoreRAII {
public:
    Cat *m_cat;

    CatStore() {
        m_cat = Cat::getInstance();
    }

    ~CatStore() {
        delete m_cat;
    }

    Cat *getCat() {
        return m_cat;
    }
};

6.建造者模式(生成器模式)

生成器模式将一个复杂对象的构建与表示分离,使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。

在这里插入图片描述


建造者模式包含如下角色:

  • 抽象建造者类:此接口声明了在所有类型建造者中通用的产品构造步骤。
  • 具体建造者类:实现建造者接口,提供构造过程的不同实现,并在构造过程完成后,提供产品的实例。
  • 产品类:要创建的复杂对象。
  • 指挥者类:调用具体建造者来创建复杂对象的各个部分,不涉及具体产品的信息,只负责保证对象各部分完整地按照某种顺序创建。

建造者模式的优点:

  1. 生成不同形式的产品时,可以复用相同的制造代码。
  2. 可以分步创建对象,暂缓创建步骤或递归运行创建步骤。
  3. 可以将复杂构造代码从产品的业务逻辑中分离出来,符合单一职责原则
  4. 如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,容易进行扩展,符合开闭原则

建造者模式的缺点:

  1. 造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制
  2. 由于该模式需要新增多个类,因此代码整体复杂程度会有所增加。
#include <iostream>
#include <string>

using namespace std;

/* 产品类 */
class Cat {
private:
    string m_leg; // 腿
    string m_tail; // 尾巴
    
public:
    const string &getLeg() const {
        return m_leg;
    }

    void setLeg(const string &leg) {
        m_leg = leg;
    }

    const string &getTail() const {
        return m_tail;
    }

    void setTail(const string &tail) {
        m_tail = tail;
    }
};

/* 抽象建造者 */
class Builder {
protected:
    Cat *m_cat = new Cat();

public:
    virtual void buildLeg() = 0;

    virtual void buildTail() = 0;

    virtual Cat *createCat() = 0;

    virtual ~Builder() {
        delete m_cat;
    }
};

/* 具体构建者 */
class DragonLiBuilder : public Builder {
public:
    void buildLeg() override {
        m_cat->setLeg("狸");
    }

    void buildTail() override {
        m_cat->setTail("花");
    }

    Cat *createCat() override {
        return m_cat;
    }
};

/* 具体构建者 */
class RagdollBuilder : public Builder {
public:
    void buildLeg() override {
        m_cat->setLeg("布");
    }

    void buildTail() override {
        m_cat->setTail("偶");
    }

    Cat *createCat() override {
        return m_cat;
    }
};

/* 指挥者 */
class Director {
private:
    Builder *m_builder;

public:
    explicit Director(Builder *builder) {
        m_builder = builder;
    }

    Cat *construct() {
        m_builder->buildLeg();
        m_builder->buildTail();
        return m_builder->createCat();
    }

    ~Director() {
        delete m_builder;
    }
};

int main() {
    Director dragonLiDirector(new DragonLiBuilder);
    Cat *dragonLi = dragonLiDirector.construct();
    cout << dragonLi->getLeg() << dragonLi->getTail() << endl;

    Director ragdollDirector(new RagdollBuilder);
    Cat *ragdoll = ragdollDirector.construct();
    cout << ragdoll->getLeg() << ragdoll->getTail() << endl;

    return 0;
}

atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main 
狸花
布偶
atreus@MacBook-Pro % 

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

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

相关文章

20230308 Apdl lsdyna两杆撞击案例学习笔记

本次模拟使用的是ANSYS 16.0 一、设置Element type 首先打开APDL界面 添加element type 在LS-DYNA Explicit选择条件下,选择3D solid 164 二、设置材料类型 选择material models 选择Elastic-Isotropic-输入 Density:密度 EX:杨氏模量 NUXY:泊松比 三、几何模型建…

小应用记账本-第2章-数据库设计

小应用记账本-第2章-数据库设计 在上一章《小应用记账本-第1章-需求分析》已经罗列了我们需要的功能&#xff0c;因为很简单&#xff0c;所以这一章就来设计数据库吧。 Account表&#xff1a;账户表 字段名类型说明取值idint账户idaccount_namevarchar账户名称remaining_sumd…

【目标检测论文解读复现NO.33】改进YOLOv5的新能源电池集流盘缺陷检测方法

前言此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c;…

python+opencv生成较真实的车牌号码图片

本文参考github代码&#xff1a;https://github.com/loveandhope/license-plate-generator 效果&#xff1a; 一、代码目录结构&#xff1a; font目录下存放车牌中文、字符的ttf字体 images目录下存放蓝色底牌、新能源绿色底牌、污渍&#xff08;噪声&#xff09;的图片 完整…

嵌入式物联网毕业设计选题智能图像识别项目-stm32mp157 linux开发板

stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器&#xff0c;集成2个Cortex-A7核和1个Cortex-M4 核&#xff0c;A7核上可以跑Linux操作系统&#xff0c;M4核上可以跑FreeRT…

ControlNet-有条件图文生成论文阅读

文章目录摘要算法&#xff1a;ControlNetControlNet in Image Diffusion ModelTrainingImproved Training实验Canny edgesHough linesHuman scribblesHED boundary mapOpenpifpaf poseOpenposeADE20K segmentation mapCOCO-Stuff segmentation mapDIODE normal mapDepth-to-Ima…

蓝桥冲刺31天之第六天

今天是摆子的一天&#xff0c;明天我要肝一整天的第四题&#xff01;&#xff01;&#xff01; PS&#xff1a;一个普通的排序罢了 import java.io.*; import java.util.Arrays; import java.util.Scanner;/*** ClassName 考勤刷卡* Description TODO* Author 小怂很怂* Date 2…

DataX与DB2导入导出案例

DataX与DB2导入导出案例 文章目录DataX与DB2导入导出案例0. 写在前面1. DB2介绍2. DB2数据库对象关系3. 安装前的准备3.1 安装依赖3.2 修改配置文件 sysctl.conf3.3 修改配置文件 limits.conf4. 安装4.1 预检查4.2 添加组和用户4.3 创建实例4.4 创建实例库、开启服务4.5 连接5.…

在CentOS7上静默安装Oracle19c

1.下载Oracle 官方安装包下载路径&#xff08;需要登录Oracle账号&#xff09;&#xff1a; https://www.oracle.com/database/technologies/oracle-database-software-downloads.html#19c 可选择windows/Linux平台对应的安装包&#xff0c;我选择Linux x86-64、ZIP包下载&…

分析linux内核移植中vmlinux可执行文件是如何生成的?以及 uImage/zImage/Image/vmlinx之间关系

一&#xff1a;分析linux内核移植中vmlinux可执行文件是如何生成的&#xff1f; 1&#xff1a;进入内核源码顶层目录下打开Makefile文件&#xff0c;搜索vmlinux 这里构建vmlinux的命令使用了makefile的内置函数call。这是一个比较特殊的内置函数&#xff0c;make使用它来引用…

Go语言学习编程实践:五种模式解决go中的并发问题

五种模式解决go中的并发问题For-Select-Done扇入模式从流中获取前 n 个值订阅模式地图模式过滤模式For-Select-Done 我们应该防止程序中发生任何泄露。所以我们应该对于留在程序中的go例程发送信号&#xff0c;让它知道它可以退出。 最常见的就是将for-select循环与通道结合起…

UEFI启动流程

以上是UEFI系统运行的7个阶段&#xff0c;下边是详细描述&#xff1a; SEC阶段&#xff1a;&#xff08;安全验证&#xff09; 1、接收和处理系统的启动&#xff0c;重启&#xff0c;异常信号&#xff1b; 2、SEC阶段特色功能“Cache As RAM&#xff08;CAR&#xff09;”&am…

英伦四地到底是什么关系?

英格兰、苏格兰、威尔士和北爱尔兰四地到底是什么关系&#xff0c;为何苏格兰非要独立&#xff1f;故事还要从中世纪说起。大不列颠岛位于欧洲西部&#xff0c;和欧洲大陆隔海相望。在古代&#xff0c;大不列颠岛和爱尔兰属于凯尔特人的领地。凯尔特人是欧洲西部一个庞大的族群…

Caddy2学习笔记——Caddy2反向代理Frp内网穿透和反向代理PVE

一、环境概述 本人拥有一个国内云服务商的云主机和一个备案好的域名&#xff0c;通过caddy2来作为web服务器。 我的云主机是公网ip&#xff0c;地址为&#xff1a;43.126.100.78&#xff1b;我备案好的域名是&#xff1a;hotgirl.com 。后面的文章都以上述的ip和域名来进行讲解…

Actipro WinForms Studio Crack

Actipro WinForms Studio Crack 已验证Microsoft.NET 7兼容性。 添加了MetroDark配色方案。 添加了支持MetroLight和MetroDark颜色方案的MetroScrollBarRenderer。 添加了IWindowsColorScheme接口&#xff0c;该接口将替换对WindowsColorScheme的大多数引用。 添加了IWindowsCo…

Zookeeper客户端ZkClient、Curator的使用,史上最详细的教程来啦~

1 前言 本文主要介绍了操作Zookeeper的几种客户端的基础使用&#xff0c;希望对老铁们会有所帮助。 可以去操作zookeeper创建、删除、查询、修改znode节点 2 Zookeeper服务器客户端分类 目前&#xff0c;Zookeeper服务器有三种Java客户端&#xff1a; Zookeeper、Zkclient和…

inquirerjs

inquirerjs inquirerjs是一个用来实现命令行交互界面的工具集合。它帮助我们实现与用户的交互交流&#xff0c;比如给用户一个提醒&#xff0c;用户给我们一个答案&#xff0c;我们根据用户的答案来做一些事情&#xff0c;典型应用如plop等生成器工具。 npm install inquirer…

软测面试了一个00后,绝对能称为是内卷届的天花板

前言 公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资也不低&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。令我印象最深的是一个00后测试员&#xf…

certum验证域名所有权

Certum证书支持 Email、文件上传、DNS解析 验证域名所有权。1 .Email 方式请确认自己域名已开通&#xff0c;域名邮箱。仅支持以下邮箱&#xff1a;adminyourdomain.comadministratoryourdomain.comwebmasteryourdomain.compostmasteryourdomain.comhostmasteryourdomain.com收…

深度学习笔记:卷积神经网络(1)

1 卷积神经网络整体结构 卷积神经网络&#xff08;CNN&#xff09;相比全连接网络多了卷积层和池化层。对于全连接网络&#xff0c;所有相邻层的神经元都用Affine层进行连接&#xff0c;如图中即为Affine-ReLU的连接组合。 卷积神经网络则包含卷积层和池化层与激活函数相连&a…