在C++中,工厂模式的思考(《C++20设计模式》及常规设计模式对比)

文章目录

  • 一、前言
  • 二、讲解
    • 1、构造函数的弊端
    • 2、工厂方法(解决上述弊端)
    • 3、简单工厂
      • 3.1 **UML类图**
      • 3.2 **实现**
    • 4、工厂模式
      • 4.1 **UML类图**
      • 4.2 **实现**
    • 5、抽象工厂
      • 5.1 **UML类图**
      • 5.2 **实现**
  • 三、总结

一、前言

在看《C++20设计模式》一书中产生了疑惑,就是经典工厂模式与这一书中的讲解差别很大,在此分享我心中的疑惑。

  • 讲解的方式不一样
    • 经典工厂模式分为三类 —— 简单工厂、工厂模式、抽象工厂。
    • 《C++20设计模式》一书是这么讲解的 —— 工厂方法、工厂、抽象工厂

这里说一下,其实他们两个讲解的东西都是同一个东西,只不过讲解的侧重点不同,而且《C++20设计模式》讲的东西还少了工厂模式的讲解。如果你仔细看书中的例子就会发现,这里《C++20设计模式》中的工厂指的是经典工厂中的简单工厂。

  • 如何统一经典的工厂模式和《C++20设计模式》一书中的工厂模式。

    • 他们对于为什么要有工厂模式的目的不同,也其实就是讲解方式的不同。

      • 经典工厂模式的目的: 使得创建对象的过程与使用对象的过程分离,高代码的可维护性和可扩展性。
      • 《C++20设计模式》工厂模式: 普通构造函数没法对参数进行验证,所以使用工厂模式。

下面是笔者认为,应该正确的讲解方式,可以统一 经典工厂模式的讲解和《C++20设计模式》中的工厂模式的讲解。

相关代码可以在这里,如有帮助给个star!AidenYuanDev/design_patterns_in_modern_Cpp_20

二、讲解

1、构造函数的弊端

无法对要进行创建的对象的参数进行验证
比如说救生员对象要求是八块腹肌,你却创建了六块腹肌,也即是一个不符合要求的对象,我们正常的需求肯定是不创建这个对象,或者创建一个空对像,因为它不符合要求嘛!但是构造函数却做不到这一点!

因为,构造函数不能返回任意的数据类型,

2、工厂方法(解决上述弊端)

用静态成员方法,来代替构造函数
很自然的想法嘛,既然构造函数没有返回值,那么我们就用成员函数嘛!成员函数不是有返回值嘛,那么就可以进行参数验证啦!

使用静态成员函数,是为了在创建对象之前就可以调用这个方法(因为这个方法就是为了创建对象,肯定要在创建对象之前就能调用嘛!所以用静态!

实现

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

class Product_Base {
protected:
    int a;
    int b;
    Product_Base(int a, int b) : a(a), b(b) {}
};

class Product : public Product_Base {
    int c;

protected:
    Product(int a, int b, int c) : Product_Base(a, b), c(c) {}

public:
    static unique_ptr<Product> new_product(int a, int b, int c) {
        if (a < 0) return nullptr;
        return unique_ptr<Product>(new Product(a, b, c));
    }
    void show() { cout << a << '\t' << b << '\t' << c << endl; }
};

int main() {
    unique_ptr<Product> p1 = Product::new_product(4, 5, 6);
    p1->show();
    return 0;
}

3、简单工厂

现在就是经典工厂模式的内容了,上面的代码看似已经可以很好的解决问题了,为什么还要有简单工厂呢?

  1. 使得创建对象的过程与使用对象的过程分离,提高代码的可维护性和可扩展性。(常见的答案)
  2. 工厂可以根据需要动态创建不同类型的对象,而不需要客户端了解具体的创建逻辑。
  3. 可以在工厂中判断对象与对象之间的关系。

3.1 UML类图

请添加图片描述

3.2 实现

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

class Product_Base{
protected:
    int a;
    int b;
    Product_Base(int a, int b) : a(a), b(b){}
public:
    virtual void show() = 0;
};

class Product_A : public Product_Base {
    int c;
    Product_A(int a, int b, int c) : Product_Base(a, b), c(c) {}
public:
    void show(){
        cout << a << '\t' << b << '\t' << c << endl;
    }
    static unique_ptr<Product_A> create(int a, int b, int c) {
        return unique_ptr<Product_A>(new Product_A(a, b, c));
    }
};

class Product_B : public Product_Base {
    int c;
    Product_B(int a, int b, int c) : Product_Base(a, b), c(c) {}
    
public:
    void show(){
        cout << a << '\t' << b << '\t' << c << endl;
    }
    static unique_ptr<Product_B> create(int a, int b, int c) {
        return unique_ptr<Product_B>(new Product_B(a, b, c));
    }

};

class Product_C : public Product_Base {
    int c;
    Product_C(int a, int b, int c) : Product_Base(a, b), c(c) {}
    friend class Simple_Factor;
public:
    void show(){
        cout << a << '\t' << b << '\t' << c << endl;
    }
    static unique_ptr<Product_C> create(int a, int b, int c) {
        return unique_ptr<Product_C>(new Product_C(a, b, c));
    }

};

enum class Product_Type {
    A,
    B,
    C
};

class Simple_Factor{
public:
    static unique_ptr<Product_Base> creater_producter(Product_Type type, int a, int b, int c) {
        switch (type) {
        case Product_Type::A:
            if (a < 0) return nullptr;
            return Product_A::create(a, b, c); 
            case Product_Type::B:
            if (b < 0) return nullptr;
            return Product_B::create(a, b, c);
        case Product_Type::C:
            if (c < 0) return nullptr;
            return Product_C::create(a, b, c);
        }
        return nullptr;
    }
};

int main() { 
    unique_ptr<Product_Base> p = Simple_Factor::creater_producter(Product_Type::A, 4, 5, 6);
    p->show();
    return 0; 
}

4、工厂模式

上面的简单工厂模式的缺点是当新增产品的时候就要去修改工厂的类,这就违反了开放封闭原则(对扩展开发,对修改关闭)于是,就出现了工厂方法模式,也就是工厂模式。

工厂抽象,有新的产品直接创建新的工厂就可以

4.1 UML类图

请添加图片描述

4.2 实现

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

class Product_Base{
protected:
    int a;
    int b;
    Product_Base(int a, int b) : a(a), b(b){}
public:
    virtual void show() = 0;
};

class Product_A : public Product_Base {
    int c;
    Product_A(int a, int b, int c) : Product_Base(a, b), c(c) {}
public:
    void show(){
        cout << a << '\t' << b << '\t' << c << endl;
    }
    static unique_ptr<Product_A> create(int a, int b, int c) {
        return unique_ptr<Product_A>(new Product_A(a, b, c));
    }
};

class Product_B : public Product_Base {
    int c;
    Product_B(int a, int b, int c) : Product_Base(a, b), c(c) {}
    
public:
    void show(){
        cout << a << '\t' << b << '\t' << c << endl;
    }
    static unique_ptr<Product_B> create(int a, int b, int c) {
        return unique_ptr<Product_B>(new Product_B(a, b, c));
    }

};

class Product_C : public Product_Base {
    int c;
    Product_C(int a, int b, int c) : Product_Base(a, b), c(c) {}
    friend class Simple_Factor;
public:
    void show(){
        cout << a << '\t' << b << '\t' << c << endl;
    }
    static unique_ptr<Product_C> create(int a, int b, int c) {
        return unique_ptr<Product_C>(new Product_C(a, b, c));
    }

};


enum class Product_Type {
    A,
    B,
    C
};

class Factor_Base{
public:
    virtual unique_ptr<Product_Base> new_product(int a, int b, int c) = 0;
};

class Factor_A : public Factor_Base {
public:
    unique_ptr<Product_Base> new_product(int a, int b, int c) {
        if (a < 0) return nullptr;
        return Product_A::create(a, b, c);
    }
};

class Factor_B : public Factor_Base {
public:
    unique_ptr<Product_Base> new_product(int a, int b, int c) {
        if (b < 0) return nullptr;
        return Product_B::create(a, b, c);
    }
};

int main() { 
    unique_ptr<Factor_Base> factor_a = make_unique<Factor_A>();
    unique_ptr<Product_Base> product_a = factor_a->new_product(1, 5, 7);
    product_a->show();
    return 0; 
}

5、抽象工厂

这个模式比普通的工厂模式抽象一点。可以做到一个工厂生产多个产品,比如苹果工厂可以生产苹果也就是生产苹果汁。

N个产品M个工厂。总结:工厂可以灵活的生产商品。

5.1 UML类图

请添加图片描述

5.2 实现

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

class Product_Base {
protected:
    int a;
    int b;
    Product_Base(int a, int b) : a(a), b(b) {}

public:
    virtual void show() = 0;
};

class Product_A : public Product_Base {
    int c;
    Product_A(int a, int b, int c) : Product_Base(a, b), c(c) {}

public:
    void show() { cout << a << '\t' << b << '\t' << c << endl; }
    static unique_ptr<Product_A> create(int a, int b, int c) { return unique_ptr<Product_A>(new Product_A(a, b, c)); }
};

class Product_B : public Product_Base {
    int c;
    Product_B(int a, int b, int c) : Product_Base(a, b), c(c) {}

public:
    void show() { cout << a << '\t' << b << '\t' << c << endl; }
    static unique_ptr<Product_B> create(int a, int b, int c) { return unique_ptr<Product_B>(new Product_B(a, b, c)); }
};

class Product_C : public Product_Base {
    int c;
    Product_C(int a, int b, int c) : Product_Base(a, b), c(c) {}
    friend class Simple_Factor;

public:
    void show() { cout << a << '\t' << b << '\t' << c << endl; }
    static unique_ptr<Product_C> create(int a, int b, int c) { return unique_ptr<Product_C>(new Product_C(a, b, c)); }
};

enum class Product_Type { A, B, C };

class Factor_Base {
public:
    virtual unique_ptr<Product_Base> new_product1(int a, int b, int c) = 0;
    virtual unique_ptr<Product_Base> new_product2(int a, int b, int c) = 0;
};

class Factor_A : public Factor_Base {
public:
    unique_ptr<Product_Base> new_product1(int a, int b, int c) {
        if (a < 0) return nullptr;
        return Product_A::create(a, b, c);
    }
    unique_ptr<Product_Base> new_product2(int a, int b, int c) {
        if (a < 0) return nullptr;
        return Product_B::create(a, b, c);
    }
};

class Factor_B : public Factor_Base {
public:
    unique_ptr<Product_Base> new_product1(int a, int b, int c) {
        if (b < 0) return nullptr;
        return Product_B::create(a, b, c);
    }
};

int main() {
    unique_ptr<Factor_Base> factor_a = make_unique<Factor_A>();
    unique_ptr<Product_Base> product_2 = factor_a->new_product2(1, 5, 7);
    product_2->show();
    return 0;
}

三、总结

工厂模式的优点:

  1. 使得创建对象的过程与使用对象的过程分离,高代码的可维护性和可扩展性。
  2. 使用工厂模式可以对参数进行验证。

最后如果有帮助,麻烦点个赞吧!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【软件测试】快速定位bug,编写测试用例

作为一名测试人员如果连常见的系统问题都不知道如何分析&#xff0c;频繁将前端人员问题指派给后端人员&#xff0c;后端人员问题指派给前端人员&#xff0c;那么在团队里你在开发中的地位显而易见 &#xff0c;口碑、升值、加薪那应该是你遥不可及的梦 但是作为测试人员来说&…

【ARMv8/v9 GIC 系列 5 -- GIC GICD_CTRL 使用详细介绍】

文章目录 GICD_CTRLGICD_CTLR 寄存器结构RWP&#xff08;Register Write Pending&#xff09;E1NWF&#xff08;Enable 1 of N Wakeup Functionality&#xff09;DS&#xff08;Disable Security&#xff09; 亲和性路由&#xff08;Affinity Routing&#xff09;ARE_NSARE_S 中…

华侨大学24计算机考研数据速览,专硕22408复试线290分,学硕11408接收调剂!

华侨大学计算机专业创建于1980年&#xff0c;是福建省最早设立计算机专业的高校之一。1982年成立计算机系&#xff0c;2008年成立计算机科学与技术学院。根据“华侨大学计算机科学与技术学院网站”资料&#xff0c;该院有计算机科学与技术、软件工程、网络工程3个本科专业&…

Mysql-基础-DDL操作

1、数据库操作 查询 查询所有数据库 show databases; 创建 创建数据库 create database [if not exists] 数据库名 使用及查询 use 数据库名 select database() 查询当前所处数据库 删除 drop database [if not exists] 数据库名 2、表操作 查询当前库中的所…

使用Python绘制彩虹效果:动态彩虹动画

文章目录 引言准备工作前置条件 代码实现与解析导入必要的库初始化Pygame定义绘制彩虹函数定义颜色列表主循环 完整代码 引言 彩虹是自然界中最美丽的现象之一。通过编程&#xff0c;我们可以将这一奇妙的景象带到屏幕上。在这篇博客中&#xff0c;我们将使用Python来创建一个…

如何优化网站SEO排名?

选择那些容易排名的关键词。使用工具找到那些竞争少但有流量的词语。其次&#xff0c;内部链接非常重要。通过合理的内部链接&#xff0c;可以提升各个页面的权重。 增加FAQ部分能帮助你捕捉更多的长尾关键词流量。争取出现在精选摘要的位置&#xff0c;可以直接提升你的曝光率…

django 逆向生成对应数据库表的models模型类 —— python

一&#xff0c;在setting.py中配置好连接数据库的参数 在setting中的DATABASESZ中配置默认参数&#xff0c;并在INSTALLED_APPS中导入模块名。 DATABASES {default:{ENGINE: django.db.backends.mysql, # 数据库引擎NAME: jljupcs, # 数据库名称HOST: 127.0.0.1, # 数据库…

【设计模式】策略模式(定义 | 特点 | Demo入门讲解)

文章目录 定义策略模式的结构 QuickStart | DemoStep1 | 策略接口Step2 | 策略实现Step3 | 上下文服务类Step4 | 客户端 策略模式的特点优点缺点 定义 策略模式Strategy是一种行为模式&#xff0c;它能定义一系列算法&#xff0c;并将每种算法分别放入到独立的类中&#xff0c…

解决pip安装时的“SyntaxError: invalid syntax”错误

项目场景&#xff1a; 项目中有新的成员加入时&#xff0c;第一步就是安装开发环境&#xff0c;然而往往同样的机器、同样的配置&#xff0c;我们却总能遇到各种各样不同的问题。 今天分享一个简单的操作问题。 问题描述 项目用到pandas&#xff0c;安装pandas时遇到Syntax…

代码随想录-Day46

121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从…

CAN学习笔记

学习链接&#xff1a;CAN学习笔记&#xff08;1&#xff09;_can sjw-CSDN博客 内容全部取自链接&#xff0c;非原创。用于自己学习和记录&#xff0c;如有错误请指正。如果侵权了&#xff0c;请联系我删掉。 CAN主要有两种物理层&#xff0c;1.闭环的ISO11898 2.开环的ISO1…

MSI安装包安装的Mysql8,配置文件my.ini在哪儿?

版本 我安装的版本是8.0.36&#xff0c;server根目录下没有配置文件。 文件位置 首先找到对应的windows服务 右击属性&#xff0c;可以看到启动参数&#xff0c;启动参数中有配置文件的路径 比如我的配置文件在"C:\ProgramData\MySQL\MySQL Server 8.0\my.ini"

XHS xs逆向分析

已经把所有的侵权地方删除&#xff0c;望批准 前言 1.本文单纯学习jsvmp和交流&#xff0c;无任何其他意图 2.学习jsvmp&#xff0c;通过插桩和算法还原。 问&#xff1a;什么是vmp&#xff1f; JSVMP&#xff08;JavaScript Virtual Machine Protocol&#xff09;是一种…

严蔚敏数据结构(C语言版)吴伟民宁编著清华大学计算机系列教材+题集+配套题库+笔记+习题PDF电子版

今天分享的是 严蔚敏数据结构&#xff08;C语言版&#xff09;题集配套题库笔记习题PDF电子版 注&#xff1a;本资源搜集于网络&#xff0c;仅供学习交流&#xff0c;严禁用于商业用途 内容简介&#xff1a; “数据结构”是计算机程序设计的重要理论技术基础&#xff0c;它…

002 使用kibana操作ElasticSearch7.x

文章目录 4.使用kibana操作es4.1.文档操作1.put方式发送数据2.post方式发送数据3.查看索引文档 GET4.更新文档 POST5.删除文档&索引 DELETE6.批量添加数据_bulk 4.2.Query DLS(查询领域对象语言)1.url 检索数据语法2.查询所有数据3.查询全部数据并排序4.查询全部数据排序并…

蓝蜂网关接入雄安新区物联网统一开放平台应用案例

蓝蜂网关接入雄安新区物联网统一开放平台案例 一、应用背景 为响应国家《河北雄安新区规划纲要》&#xff0c;由中国雄安集团数字城市科技有限公司牵头&#xff0c;以中移物联网有限公司为牵头单位的联合体&#xff0c;构建了雄安新区物联网统一开放平台&#xff08;简称雄安…

2024英语专业大学排名一览表

英语专业排名前10名的大学是&#xff1a;北京大学、北京外国语大学、上海外国语大学、黑龙江大学、上海交通大学、南京大学、浙江大学、广东外语外贸大学、清华大学、北京航空航天大学&#xff0c;以下是查大学网&#xff08;www.chadaxue.com&#xff09;整理的2024英语专业大…

AI与大模型工程师证书研修班报名啦!

人工智能大模型是指拥有超大规模参数&#xff08;通常在十亿个以上&#xff09;、超强计算资源的机器学习模型&#xff0c;能够处理海量数据&#xff0c;完成各种复杂任务&#xff0c;如自然语言处理、图像识别等。计算机硬件性能不断提升&#xff0c;深度学习算法快速优化&…

js替换对象里面的对象名称

data为数组&#xff0c;val为修改前的名称&#xff0c;name为修改后的名称 JSON.parse(JSON.stringify(data).replace(/val/g, name)) &#xff1b; 1.替换data里面的对象tenantInfoRespVO名称替换成tenantInfoUpdateReqVO 2.替换语句&#xff1a; 代码可复制 let tenantInf…

安装windows服务,细节

1、选中服务代码&#xff0c;右键添加安装程序。 2、安装程序的权限一定改为local,否则安装时会提示null错误。 3、安装服务 InstallUtil D:\vs2022work\testFW\testFW\bin\Debug\testFW.exe p:InstallUtil 需要新建环境变量才能直接使用&#xff08;找到InstallUtil 工具所在…