C++设计模式——工厂模式 :简单工厂、工厂方法、抽象工厂

工厂模式可以分为三种,简单工厂模式,工厂方法模式和抽象工厂模式。
那么,这三种工厂模式长啥样,又为啥会衍生出这三种模式来呢?本篇和大家一起来学习总结一下。

一、简单工厂模式

简单工厂SimpleFactory 负责创建所有实例的内部逻辑。
工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。

简单工厂模式

//SimpleFactory.h
#pragma once

#include <iostream>
#include <string>
#include <functional>

using namespace std;
#define MYTRACE()  { cout << __FUNCTION__  << std::endl; }

/**
* 产品的抽象类(抽象产品类)
*/
class AbstractProduct
{
public:
	virtual ~AbstractProduct() { 
		MYTRACE ()
	}
	virtual void show() = 0;
};

/**
* 中国产品 (具体产品类)
*/
class ChineseProduct : public AbstractProduct
{
public:
	ChineseProduct() {}
	~ChineseProduct() {
		MYTRACE()
	}

	void show() override
	{
		MYTRACE()
	}
};

/**
* 日本产品 (具体产品类)
*/
class JapaneseProduct : public AbstractProduct
{
public:
	JapaneseProduct() {}
	~JapaneseProduct() {
		MYTRACE()
	}

	void show() override
	{
		MYTRACE()
	}
};


/*
* 具体工厂类:负责每一个具体产品的创建业务逻辑
*/

class SimpleFactory
{
public:
	enum  class ProductType {ChineseProductType,JapaneseProductType};

	static AbstractProduct* CreateProduct(ProductType type)
	{
		switch (type)
		{
		case SimpleFactory::ProductType::ChineseProductType:
			return new ChineseProduct;
		case SimpleFactory::ProductType::JapaneseProductType:
			return new JapaneseProduct;
		}
	}
};


// main.cpp
#include <iostream>
#include "simpleFactory.h"
#include <vector>

int main()
{
    std::vector<AbstractProduct*> v;
    v.resize(2);
        
    v[0] = SimpleFactory::CreateProduct(SimpleFactory::ProductType::ChineseProductType);
    v[1] = SimpleFactory::CreateProduct(SimpleFactory::ProductType::JapaneseProductType);
    
    for (int i = 0; i < v.size(); ++i) {
        if (v[i] != nullptr) {
            v[i]->show();

            delete v[i];
            v[i] = nullptr;
        }
    }
    return 0;
}

简单工厂优缺点

优点:
(1)帮助封装:实现组件封装,面向接口编程
(2) 延迟了子类的实例化
(3)解耦合:客户端和具体实现类的解耦合

缺点:
(1)可能增加客户端的复杂度
(2)不方便扩展子工厂

二、工厂方法模式

在这里插入图片描述

//PolymorphicFactory.h
#pragma once

#include <iostream>
#include <string>
#include <functional>

using namespace std;
#define MYTRACE()  { cout << __FUNCTION__  << std::endl; }

/**
* 产品的抽象类(抽象产品类)
*/
class AbstractProduct
{
public:
	virtual ~AbstractProduct() {MYTRACE()}
	virtual void makeProduct() = 0;
};

class AbstractFactory 
{
public:
	virtual ~AbstractFactory() { MYTRACE() }
	virtual AbstractProduct* createProduct() = 0;
};

/**
* 中国产品 (具体产品类)
*/
class ChineseProduct : public AbstractProduct
{
public:
	ChineseProduct() {}
	~ChineseProduct() { MYTRACE() }

	void makeProduct() override { MYTRACE() }
};


class ChineseFactory : public AbstractFactory
{
public:
	virtual AbstractProduct* createProduct() override {
		MYTRACE()
		return new ChineseProduct;
	}
};


/**
* 日本产品 (具体产品类)
*/
class JapaneseProduct : public AbstractProduct
{
public:
	JapaneseProduct() {}
	~JapaneseProduct() { MYTRACE()}

	void makeProduct() override{ MYTRACE()}
};

class JapaneseFactory : public AbstractFactory
{
public:
	virtual AbstractProduct* createProduct() override {
		MYTRACE()
		return new JapaneseProduct;
	}
};
#include <iostream>
#include "PolymorphicFactory.h"
#include <cstdio>

int main()
{
    // 中国工厂
    AbstractFactory* c_factory = new ChineseFactory;
    // 开产线
    AbstractProduct* c_product =  c_factory->createProduct();
    // 制造该产品
    c_product->makeProduct();


    // 日本工厂
    AbstractFactory* j_factory = new JapaneseFactory;
    // 开产线
    AbstractProduct* j_product = j_factory->createProduct();
    // 制造该产品
    j_product->makeProduct();

    return 0;
}

工厂方法优缺点

优点:
(1)帮助封装:实现组件封装,面向接口编程
(2) 延迟了子类的实例化
(3)解耦合:客户端和具体实现类的解耦合
(4)需求改变时改动最小

缺点:
(1)新增功能时,工作量稍大

三、抽象工厂模式

AbstractFactory 模式就是用来解决这类问题:要创建一组相关或者相互依赖的对象。AbstractFactory模式关键 就是将这一组对象的创建封装到一个用于创建对象的类(ConcreteFactory)中,维护这样一个创建类总比维护n多相关对象的创建过程要简单的多。
抽象工厂模式

//Product.h
#ifndef _PRODUCT_H_
#define _PRODUCT_H_

#include <iostream>
#include <string>

using namespace std;
#define MYTRACE  { cout << __FUNCTION__  << std::endl; }

class AbstractProductA
{
public:
    virtual ~AbstractProductA(){MYTRACE}
protected:
    AbstractProductA(){MYTRACE}
private:
};


class AbstractProductB
{
public:
    virtual ~AbstractProductB(){MYTRACE}
protected:
    AbstractProductB(){MYTRACE}
private:
};


class ProductA1: public AbstractProductA
{
public:
    ProductA1(){MYTRACE}
    ~ProductA1(){MYTRACE}
protected:
private:
};


class ProductA2:public AbstractProductA
{
public:
    ProductA2(){MYTRACE}
    ~ProductA2(){MYTRACE}
protected:
private:
};


class ProductB1: public AbstractProductB
{
public:
    ProductB1(){MYTRACE}
    ~ProductB1(){MYTRACE}
protected:
private:
};


class ProductB2: public AbstractProductB
{
public:
    ProductB2(){MYTRACE}
    ~ProductB2(){MYTRACE}
protected:
private:
};

#endif //_PRODUCT_H_

// factory.h
#ifndef FACTORY_H
#define FACTORY_H


#include "product.h"

class AbstractFactory
{
public:
    virtual ~AbstractFactory(){}
    virtual AbstractProductA* createProductA() = 0;
    virtual AbstractProductB* createProductB() = 0;
protected:
    AbstractFactory(){}
};


/*!
 * \brief The ConcreteFactory1 class   生产一类产品:A1和B1
 */
class ConcreteFactory1: public AbstractFactory
{
public:
    ConcreteFactory1(){}
    ~ConcreteFactory1(){}
    AbstractProductA* createProductA() override{ return new ProductA1;}
    AbstractProductB* createProductB() override{ return new ProductB1;}
protected:
private:
};


/*!
 * \brief The ConcreteFactory2 class    生产二类产品:A2和B2
 */
class ConcreteFactory2:public AbstractFactory
{
public:
    ConcreteFactory2(){}
    ~ConcreteFactory2(){}
    AbstractProductA* createProductA() override{ return new ProductA2;}
    AbstractProductB* createProductB() override{ return new ProductB2;}
protected:
private:
};

#endif // FACTORY_H
#include <iostream>
#include "factory.h"

int main(/*int argc, char *argv[]*/)
{
     AbstractFactory* cf1  = new ConcreteFactory1;
     cf1->createProductA();
     cf1->createProductB();

     AbstractFactory* cf2  = new ConcreteFactory2;
     cf2->createProductA();
     cf2->createProductB();

     return 0;
}

抽象工厂模式
抽象工厂模式优缺点
优点:

  1. 抽象工厂封装了变化,封装了对象创建的具体细节
  2. 增加新的产品族很方便,无须修改已有系统
  3. 针对接口进行编程而不是针对具体产品对象进行编程

缺点:

  1. 增加新的产品等级结构需对原系统做较大修改(违背开放封闭)

四、总结

在前面三个部分,我们说了三种不同工厂模式的实现,以及各自的优缺点。那么,是不是说抽象工厂模式就是最好的呢,显然不是,具体的使用哪种模式,还要结合业务场景需求~

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

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

相关文章

Zabbix 6 详细安装部署教程

目录 一、安装 MySQL 数据库 二、安装 zabbix 监控平台 三、编辑配置文件 四、启动服务 五、zabbix-web 安装 zabbix web 出图展示乱码问题解决方案 zabbix 的安装部署非常简单&#xff0c;官方提供了四种安装途径&#xff0c;分别是二进制 rpm 包安装方式、源码安装方…

使用 DMA 在 FPGA 中的 HDL 和嵌入式 C 之间传输数据

使用 DMA 在 FPGA 中的 HDL 和嵌入式 C 之间传输数据 该项目介绍了如何在 PL 中的 HDL 与 FPGA 中的处理器上运行的嵌入式 C 之间传输数据的基本结构。 介绍 鉴于机器学习和人工智能等应用的 FPGA 设计中硬件加速的兴起&#xff0c;现在是剥开几层“云雾”并讨论 HDL 之间来回传…

微信小程序仿网易严选(附精选源码32套,涵盖商城团购等)

商城主要实现的功能 首页、专题、分类、购物车、我的小程序授权登陆获取用户信息首页包含品牌制造页、品牌制造详情页面、新品首发页面、人气推荐页面、各分类列表商品详情页面&#xff0c;包含常见问题、大家都在看商品列表、加入购物车、收藏商品、立即购买、下订单、选择收…

在表格中显示字典的内容(根据后端返回的数据)vue3

进入页面&#xff0c;调接口&#xff0c;后端返回数据&#xff0c;indexType为0或者1&#xff0c;要用这个数据显示字典的内容 用插槽拿到数据 写一个函数&#xff0c;在模板中使用 const { proxy } getCurrentInstance(); // 字典-指标类型 const { index_type } proxy.u…

6.保留两位小数【2023.11.28】

1.问题描述 题中将给出一个具有许多小数位的浮点数&#xff0c;请将这个数字保存至小数点后两位&#xff0c;并输出。 2.解决思路 输入一个浮点数。 程序将浮点数保留两位小数并输出。 例如&#xff1a; formatted_float "{:.2f}".format(input_float)3.代码实…

echarts图表滚动条带动页面窗口滚动条的问题

网上搜了很多方法不管用&#xff0c;后来发现每次滚动echarts或者左右滑动echarts下方都会报错&#xff0c;报错提示如下&#xff0c;看看你们的图表是否这样报错&#xff1a; 报错信息如下&#xff1a;Unable to preventDefault inside passive event listener invocation 原…

三大录屏软件推荐,让你轻松录制屏幕

录屏软件的应用变得越来越广泛&#xff0c;无论是记录屏幕上的内容以方便日后查阅&#xff0c;还是与他人分享操作过程&#xff0c;录屏软件都发挥着重要作用。然而&#xff0c;市面上的录屏软件种类繁多&#xff0c;质量参差不齐。那有没有好用的录屏软件推荐呢&#xff1f;在…

金字塔原理

金字塔原理 来自于麦肯锡公司的第一位女性咨询顾问芭芭拉•明托的著作《金字塔原理》。 原理介绍 此原理是一种重点突出、逻辑清晰、主次分明的逻辑思路、表达方式和规范动作。 金字塔的基本结构是&#xff1a;中心思想明确&#xff0c;结论先行&#xff0c;以上统下&#xff…

小功能实现(十九)生成shp文件

引入依赖 <!--shp文件相关工具--><dependency><groupId>org.geotools</groupId><artifactId>gt-shapefile</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geo…

矩阵连乘问题

1、求解矩阵连乘问题。 要求: 分别用自底向上的动态规划方法和自顶向下的备忘录方法计算最优值并构造最优解&#xff0c;通过实例比较两种方法的结果和效率。 思路 1)寻找最优子结构&#xff1a; 此问题最难就在于此&#xff0c;对于乘积的任意位置加括号都会将序列在某个…

Java 基础学习(三)循环流程控制与数组

1 循环流程控制 1.1 循环流程控制概述 1.1.1 什么是循环流程控制 当一个业务过程需要多次重复执行一个程序单元时&#xff0c;可以使用循环流程控制实现。 Java中包含3种循环结构&#xff1a; 1.2 for循环 1.2.1 for循环基础语法 for循环是最常用的循环流程控制&#xff…

智慧公厕为高速服务区公厕做出的贡献

在现代社会&#xff0c;科技的飞速发展改变了人们的生活方式&#xff0c;也深刻影响着城市的基础设施和公共服务。而在这个数字化时代的背景下&#xff0c;智慧公厕作为城市智能化管理的一部分&#xff0c;为高速服务区公厕带来了一系列的创新和贡献&#xff0c;为旅客的出行提…

C++基础 -10- 类的构造函数

类的构造函数类型一 使用this指针给类内参数赋值 class rlxy {public:int a;rlxy(int a, int b, int c){this->aa;this->bb;this->cc;cout << "rlxy" << endl;}protected:int b;private:int c; };int main() {rlxy ss(10, 20, 30); }类的构造…

\n\r:解析java中的\r、\n、\r\n、\n\r的区别

1 \r 1.1 内容 回车符,将光标定义到当前行行首 1.2 在idea中测试 1.2.1 表现形式 在\r后有新内容时,会先删除之前以前存在过的文本,即只打印\r后面的内容 1.2.2 示例代码 package Work; public class Test05 { public static void main(String[] args) { System.…

docker-compose Install OrangeHRM

OrangeHRM 前言 OrangeHRM 是一个全面的人力资源管理(HRM) 系统,它包含任何企业所需的所有基本功能。OrangeHRM旨在支持任何规模的团队,包括初创企业、中小企业以及大型跨国组织。 OrangeHRM 提前条件 OrangeHRMdocker & docker-composer 安装or

会议预告 | 求臻医学受邀参加2023·Inno China 产业创新大会

INNO CHINA 中国产业创新大会聚焦于数据驱动产业变革升级、医疗科技与产业转型升级、企业数字化转型升级、产业服务生态构建及商业智能融合发展等领域。如今&#xff0c;已成为中国新兴科技、热门赛道行业论坛、创新成果展示、参与、共创的高维度学术与产业年度相聚的节日&…

使用vue-admin-template时,需要注意的问题,包括一定要去除mock.js注释

在使用vue-admin-template等前端框架时&#xff0c;如果你没有打算用他们的mock数据&#xff0c;在生产环境下一定要注释mock引用的代码&#xff0c;虽然它没有被调用&#xff0c;但是如果你不注释&#xff0c;就会被打包进去。 找到main.js&#xff0c;看如下代码&#xff1a…

搭建一个可以发送邮箱验证码的接口,内含前端处理 接口返回、请求处理

环境搭建 在node安装好的情况下&#xff08;一般vue环境有的node也有 没有可以使用winr回车输入node -v 有版本号则已经安装好 找一个空文件夹作为此项目文件夹 点击上面的地址栏输入cmd回车 输入npm init -y 再输入npm install nodemailer安装发送邮件的插件 环境配置 使用v…

C++学习之路(十一)C++ 用Qt5实现一个工具箱(增加一个进制转换器功能)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《时间戳转换功能》功能。为了继续丰富我们的工具箱&#xff0c;今天我们就再增加一个平时经常用到的功能吧&#xff0c;就是「 进制转换 」功能。下面我们就来看看如何来规划开发一个这样的小功能并且添加到我们的工具…

苹果提醒事项怎么用?几个简单步骤就能学会!

苹果提醒事项可以帮助你轻松管理待办事项&#xff0c;让你更好地安排自己的时间和工作。但是&#xff0c;有些小伙伴可能对如何使用这个功能还有一些疑问。苹果提醒事项怎么用&#xff1f;不要担心&#xff0c;小编将为大家提供使用提醒事项的方法&#xff0c;帮助你学会如何使…