[C/C++] -- 工厂模式

工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式,而无需暴露对象创建的逻辑细节。工厂模式通过使用工厂类来创建对象,将对象的创建和使用解耦,使得系统更加灵活、可扩展和易于维护。

工厂模式主要分为三种:简单工厂模式、工厂方法模式和抽象工厂模式。每种模式都有不同的应用场景和实现方式。

1. 简单工厂模式 

简单工厂模式通过一个工厂类来负责创建不同类型的对象,客户端只需要知道工厂类的接口,而无需关心具体对象的创建过程。这种模式适用于需要创建的对象类型较少且不会频繁变化的场景。

优点

  • 将对象的创建和使用分离,客户端只需与工厂类交互,降低了耦合度。
  • 简化了客户端代码,使得客户端无需知道具体产品的创建细节。

缺点

  • 添加新产品类型需要修改工厂类,违反了开放-封闭原则。
  • 工厂类可能会变得庞大,包含过多的创建逻辑。

首先,定义一个抽象产品类 Product 和两个具体产品类 ConcreteProductAConcreteProductB

#include <iostream>

// Abstract Product
class Product {
public:
    virtual void use() const = 0;
};

// Concrete Product A
class ConcreteProductA : public Product {
public:
    void use() const override {
        std::cout << "Using Concrete Product A" << std::endl;
    }
};

// Concrete Product B
class ConcreteProductB : public Product {
public:
    void use() const override {
        std::cout << "Using Concrete Product B" << std::endl;
    }
};

接下来,定义工厂类 SimpleFactory,它包含一个静态方法 createProduct 来创建不同类型的产品:

// Simple Factory
class SimpleFactory {
public:
    enum ProductType { TypeA, TypeB };

    static Product* createProduct(ProductType type) {
        switch (type) {
            case TypeA:
                return new ConcreteProductA();
            case TypeB:
                return new ConcreteProductB();
            default:
                return nullptr;
        }
    }
};

 最后,在主函数中使用简单工厂模式创建产品并调用其方法:

int main() {
    // Create Concrete Product A
    Product* productA = SimpleFactory::createProduct(SimpleFactory::TypeA);
    if (productA) {
        productA->use();
        delete productA;
    }

    // Create Concrete Product B
    Product* productB = SimpleFactory::createProduct(SimpleFactory::TypeB);
    if (productB) {
        productB->use();
        delete productB;
    }

    return 0;
}

2. 工厂方法模式

工厂方法模式定义了一个创建对象的接口,但将具体对象的创建延迟到子类中实现。每个子类都可以根据需求来创建自己特定的对象,从而提供了一种扩展的方式。

优点

  • 具体产品的创建延迟到子类中实现,符合开放-封闭原则。
  • 每个子类可以根据需要创建特定的产品,灵活性高。

缺点

  • 每增加一个产品,都需要增加一个对应的工厂类,导致类的数量增加。
// 抽象产品
class Vehicle {
public:
    virtual void move() = 0;
};

// 具体产品
class Car : public Vehicle {
public:
    void move() override {
        cout << "Car is moving." << endl;
    }
};

class Bike : public Vehicle {
public:
    void move() override {
        cout << "Bike is moving." << endl;
    }
};

// 抽象工厂
class TransportFactory {
public:
    virtual Vehicle* createTransport() = 0;
};

// 具体工厂
class CarFactory : public TransportFactory {
public:
    Vehicle* createTransport() override {
        return new Car();
    }
};

class BikeFactory : public TransportFactory {
public:
    Vehicle* createTransport() override {
        return new Bike();
    }
};

int main() {
    TransportFactory* carFactory = new CarFactory();
    Vehicle* car = carFactory->createTransport();
    car->move();

    TransportFactory* bikeFactory = new BikeFactory();
    Vehicle* bike = bikeFactory->createTransport();
    bike->move();

    delete car;
    delete bike;
    delete carFactory;
    delete bikeFactory;

    return 0;
}

3. 抽象工厂模式

抽象工厂模式提供了一个接口,用于创建相关或依赖对象的家族,而不需要指定具体的类。它是工厂方法模式的扩展,用于创建一组相关的产品对象。

优点

  • 提供了一种创建一组相关或依赖对象的方式,保证这些对象能够协同工作。
  • 客户端与具体工厂类分离,更容易替换具体工厂类以及产品系列。

缺点

  • 扩展新的产品族比较困难,需要修改抽象工厂接口以及所有具体工厂的实现。
#include <iostream>
#include <string>

// 抽象产品类 - 椅子
class Chair {
public:
    virtual std::string getType() = 0;
};

// 具体产品类 - 现代椅子
class ModernChair : public Chair {
public:
    std::string getType() override {
        return "Modern Chair";
    }
};

// 具体产品类 - 维多利亚椅子
class VictorianChair : public Chair {
public:
    std::string getType() override {
        return "Victorian Chair";
    }
};

// 抽象产品类 - 沙发
class Sofa {
public:
    virtual std::string getType() = 0;
};

// 具体产品类 - 现代沙发
class ModernSofa : public Sofa {
public:
    std::string getType() override {
        return "Modern Sofa";
    }
};

// 具体产品类 - 维多利亚沙发
class VictorianSofa : public Sofa {
public:
    std::string getType() override {
        return "Victorian Sofa";
    }
};

// 抽象工厂类
class FurnitureFactory {
public:
    virtual Chair* createChair() = 0;
    virtual Sofa* createSofa() = 0;
};

// 具体工厂类 - 现代家具工厂
class ModernFurnitureFactory : public FurnitureFactory {
public:
    Chair* createChair() override {
        return new ModernChair();
    }

    Sofa* createSofa() override {
        return new ModernSofa();
    }
};

// 具体工厂类 - 维多利亚家具工厂
class VictorianFurnitureFactory : public FurnitureFactory {
public:
    Chair* createChair() override {
        return new VictorianChair();
    }

    Sofa* createSofa() override {
        return new VictorianSofa();
    }
};

int main() {
    // 现代家具工厂
    FurnitureFactory* modernFactory = new ModernFurnitureFactory();
    Chair* modernChair = modernFactory->createChair();
    Sofa* modernSofa = modernFactory->createSofa();

    std::cout << "Modern Furniture: " << modernChair->getType() << ", " << modernSofa->getType() << std::endl;

    // 维多利亚家具工厂
    FurnitureFactory* victorianFactory = new VictorianFurnitureFactory();
    Chair* victorianChair = victorianFactory->createChair();
    Sofa* victorianSofa = victorianFactory->createSofa();

    std::cout << "Victorian Furniture: " << victorianChair->getType() << ", " << victorianSofa->getType() << std::endl;

    // 清理
    delete modernFactory;
    delete modernChair;
    delete modernSofa;

    delete victorianFactory;
    delete victorianChair;
    delete victorianSofa;

    return 0;
}

特点:

简单工厂 Simple Factory:

把对象的创建封装在一个接口函数里面,通过传入不同的标识,返回创建的对象。

客户不用自己负责new对象,不用了解对象创建的详细过程

提供创建对象实例的接口函数不闭合,不能对修改关闭

工厂方法 Factory Method

Factory基类,提供了一个纯虚函数(创建产品),定义派生类(具体产品的工厂)负

责创建对应的产品,可以做到不同产品,在不同工厂里面创建,能够对现有工厂,

以及产品的修改关闭

实际上,很多产品是有关联关系的,属于一个产品簇,不应该放在不同的工厂里面区创建,这样

1、不符合实际的产品对象创建逻辑。2、工厂类太多,不好维护

抽象工厂 Abstract Factory

把有关联关系的,属于一个产品簇的所有产品创建的接口函数,放在一个抽象工厂里面

AbstractFactory,派生类(具体产品的工厂)应该负责该产品簇里面所有的产品

总结:

在实际应用中,选择合适的工厂模式取决于需求的复杂性和扩展性。简单工厂模式适用于产品类型较少且不频繁变化的情况;工厂方法模式适用于产品类型多且需要灵活扩展的情况;抽象工厂模式适用于需要创建一组相关产品族并保证其协同工作的情况。

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

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

相关文章

JavaEE 初阶篇-深入了解 HTTP 协议

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 HTTP 协议概述 2.0 HTTP 请求协议 2.1 请求方式的具体体现 3.0 HTTP 响应协议 3.1 常见的状态码及描述 3.2 常见的响应头 4.0 HTTP 协议解析 4.1 简单实现服务器响…

Linux/Intuition

Intuition Enumeration nmap 使用 nmap 扫描系统常见端口&#xff0c;发现对外开放了 22 和 80&#xff0c;然后扫描这两个端口的详细信息 ┌──(kali㉿kali)-[~/vegetable/HTB/Intuition] └─$ nmap -sC -sV -p 22,80 -oA nmap 10.10.11.15 Starting Nmap 7.93 ( https:…

Springboot+vue项目影城管理系统

摘 要 本论文主要论述了如何使用JAVA语言开发一个影城管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述影城管理系统的当前背景以及系统开发的目的&…

计算机SCI期刊,IF=9.657,1区TOP,2周内出版!

一、期刊名称 Neural Networks 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;7.8 中科院分区&#xff1a;1区TOP 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;选择开放出版需支付$3350 三、期刊简介 神…

Shell生成支持x264的ffmpeg安卓全平台so

安卓 FFmpeg系列 第一章 Ubuntu生成ffmpeg安卓全平台so 第二章 Windows生成ffmpeg安卓全平台so 第三章 生成支持x264的ffmpeg安卓全平台so&#xff08;本章&#xff09; 文章目录 安卓 FFmpeg系列前言一、实现步骤1、下载x264源码2、交叉编译生成.a3、加入x264配置4、编译ffmp…

【ZIP技巧】ZIP分卷压缩包如何解压?

经过压缩的文件仍然过大&#xff0c;大家可能都会选择“分卷压缩”来压缩ZIP文件&#xff0c;但是当我们将压缩包分卷之后&#xff0c;解压的时候该如何解压&#xff1f;今天我们分享两个ZIP分卷压缩包如何解压的方法给大家。 一、 我们可以直接点击第一个分卷压缩包&#xf…

DHC:用于类别不平衡的半监督医学图像分割的双重去偏异构协同框架

文章目录 DHC: Dual-Debiased Heterogeneous Co-training Framework for Class-Imbalanced Semi-supervised Medical Image Segmentation摘要方法Distribution-aware Debiased Weighting (DistDW)Difficulty-aware Debiased Weighting (DiffDW) 实验结果 DHC: Dual-Debiased He…

Context capture/Pix4Dmapper/AutoCAD/CASS/EPS软件的安装流程与使用方法;土方量计算;无人机摄影测量数据处理

目录 专题一 无人机摄影测量技术应用现状及其发展 专题二 基本原理和关键技术讲解 专题三 无人机影像外业数据获取 专题四 数据处理环境建立与软件熟悉 专题五 GNSS数据土方量计算 专题六 基于无人机影像数据的正射影像制作 专题七 基于无人机影像数据的三维模型制作 专…

TS流加扰的判断

一般情况下&#xff0c;1套节目是否加扰 在SDT表中或者包头的加扰位2处判断。 1.SDT表的free_CA_mode0是未加密&#xff0c;1是加密&#xff1b;在SDT表中&#xff0c;只是一个规范&#xff08;如果节目加密了&#xff0c;应该让free_CA_mode1&#xff09;。实际上&#xff0c…

燃气电力瓶装气行业入户安检小程序开发

我们开发的小区业主入户安检小程序&#xff0c;旨在满足燃气、电力以及其他需要入户安检的行业需求。该程序支持自定义安检项目&#xff0c;实现线下实地安检与线上数据保存的完美结合。在安检过程中&#xff0c;我们可以拍照或录像&#xff0c;以确保安检的透明性和可追溯性&a…

【C++】-【QT】类库使用-001

1主窗口创建 1.1【makefile】配置 1 源码 QT widgetsSOURCES main.cpp2 图示 1.2源码 1 源码 #include <QWidget> #include <QApplication>using namespace std;int main(int argc,char *argv[]) {QApplication a(argc,argv);QWidget w;w.show();return a…

应聘项目经理,软考证书会是一个加分项吗?

加分项是必需的&#xff0c;特别是IT行业的项目经理职位。您可以在各大招聘网站上搜索项目经理职位&#xff0c;前景好、薪资高、待遇好的项目经理岗位&#xff0c;基本上都有证书的要求。非IT行业项目经理&#xff0c;可以考虑PMP证书或者其他与专业相关的证书&#xff0c;比如…

Android 高版本实现沉浸式状态栏

目前实现的android高版本沉浸式状态栏分为两类&#xff1a; 1、是纯透明状态栏&#xff1b; 2、是纯透明状态栏&#xff0c;但是状态栏字体是黑色&#xff1b; 将状态栏的代码封装到BaseActivity中更方便使用&#xff1a; BaseActivity: public abstract class BaseActivit…

大模型微调实战之强化学习 贝尔曼方程及价值函数(一)

大模型微调实战之强化学习 贝尔曼方程及价值函数 强化学习&#xff08;RL&#xff09;是机器学习中一个话题&#xff0c;不仅在人工智能方面。它解决问题的方式与人类类似&#xff0c;我们每天都在学习并在生活中变得更好。 作为一名大模型学习者&#xff0c;当开始深入研究强…

校验--ECC详细分析

ECC介绍 ECC 以下是针对瑞萨MCU的应用的ECC检测的详细分析。 当前公认安全有效的三大类公钥密钥体制分别为基于大数因子分解难题(RSA)、离散对数难题(DSA)和椭圆曲线离散对数&#xff08;ECC&#xff09;难题的密码体制。 保证RSA的安全性&#xff0c;则必须要增加密钥长度…

【最优传输二十九】Wasserstein Barycenterand Its Application to Texture Mixing

motivation 本文提出了离散概率分布的平均作为Monge-Kantorovich最优传输空间重心的新定义。为了克服数值求解这类问题所涉及的时间复杂性&#xff0c;原始的Wasserstein度量被一维分布上的切片近似所取代。这使我们能够引入一种新的快速梯度下降算法来计算点云的Wasserstein质…

Cesium 问题:billboard 加载未出来

文章目录 问题分析问题 接上篇 Cesium 展示——图标的依比例和不依比例缩放,使用加载 billboard 时,怀疑是路径的原因导致未加载成功 分析 原先

初步了解Kubernetes

目录 1. K8S概述 1.1 K8S是什么 1.2 作用 1.3 由来 1.4 含义 1.5 相关网站 2. 为什么要用K8S 3. K8S解决的问题 4. K8S的特性 5. Kubernetes集群架构与组件 6. 核心组件 6.1 Master组件 6.1.1 Kube-apiserver 6.1.2 Kube-controller-manager 6.1.3 kube-schedul…

算法学习008-登山爬石梯 c++动态规划/递归算法实现 中小学算法思维学习 信奥算法解析

目录 C登山爬石梯 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C登山爬石梯 一、题目要求 1、编程实现 小明周末和朋友约好了一起去爬山&#xff0c;来到山下&#xff0c;发现登山道是…

【问题实操】银河高级服务器操作系统实例分享,开机之后反复重启

1.服务器环境以及配置 物理机/虚拟机/云/容器 物理机 外网/私有网络/无网络 私有网络 处理器&#xff1a; PHYTIUM FT2000PLUS 2200 MHz 内存&#xff1a; 128 GiB 整机类型/架构&#xff1a; HIKVISION DS-V BIOS版本&#xff1a; HK 601FBE02HK 网卡&#xff1…
最新文章