工厂模式详解与应用场景

news2024/11/15 11:46:33

摘要:

工厂模式是一种常见的设计模式,它可以帮助我们在面向对象的程序设计中更好地组织和管理对象的创建过程。本文将详细介绍工厂模式的概念、三种常见的工厂模式应用场景,并提供高质量的C++代码示例,旨在帮助初学者更好地理解和应用工厂模式。

1. 工厂模式概述

工厂模式属于创建型设计模式,它提供了一种将对象的创建过程封装起来的方法。通过工厂模式,我们可以将对象的实例化与客户端代码解耦,使客户端代码不依赖于具体的对象创建方式,而是通过工厂来获取所需的对象实例。这种解耦有助于提高代码的灵活性和可维护性。

在工厂模式中,通常有三个主要角色:

抽象产品(Abstract Product):定义了产品的接口,具体产品必须实现这些接口。
具体产品(Concrete Product):实现抽象产品定义的接口,代表具体的对象实例。
工厂(Factory):负责创建具体产品的实例,客户端代码通过工厂来获取所需产品的对象。

2. 工厂模式应用场景

2.1 简单工厂模式(Simple Factory Pattern)

简单工厂模式并不属于GOF(Gang of Four)提出的23种设计模式之一,但它是工厂模式的一种基础形式。在简单工厂模式中,我们使用一个单独的工厂类来负责创建所有的产品对象。

适用场景:

当需要创建的对象较少,且创建过程相对简单时,可以考虑使用简单工厂模式。
适用于具有相同父类或接口的一组类,且客户端不需要关心具体对象的创建细节。

2.2 工厂方法模式(Factory Method Pattern)

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。这样,工厂方法模式将对象的实例化推迟到子类,符合开闭原则。

适用场景:

当需要添加新产品时,只需创建对应的具体工厂和产品类,无需修改现有代码,符合开闭原则。
适用于具有相同父类或接口的一组类,且每个子类需要不同的初始化逻辑。

2.3 抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,而无需指定具体类。通过使用抽象工厂模式,客户端可以创建并使用多个产品组合,而无需关心具体产品的实现细节。
在这里插入图片描述

适用场景:

适用于产品有多个系列(例如不同品牌的汽车和轮胎),且客户端需要使用这些系列产品。
有利于避免产品之间的不匹配问题,确保一系列产品被一起创建。

3. 三种工厂模式的区别

简单工厂模式只有一个工厂类来创建所有产品,工厂方法模式每个产品对应一个具体工厂,抽象工厂模式每个产品组合对应一个具体工厂。

简单工厂模式的客户端代码与具体产品紧密耦合,不符合开闭原则。而工厂方法模式和抽象工厂模式通过派生新的工厂类来创建新的产品,更符合开闭原则。

工厂方法模式将产品的创建推迟到子类,使得系统更具有灵活性。抽象工厂模式则在工厂的基础上提供了一系列产品组合,更适合创建一系列相关的产品。

4. C++代码示例

4.1 简单工厂模式示例

// 抽象产品
class Product {
public:
    virtual void operation() = 0;
};

// 具体产品 A
class ConcreteProductA : public Product {
public:
    void operation() override {
        std::cout << "Concrete Product A" << std::endl;
    }
};

// 具体产品 B
class ConcreteProductB : public Product {
public:
    void operation() override {
        std::cout << "Concrete Product B" << std::endl;
    }
};

// 简单工厂类
class SimpleFactory {
public:
    static Product* createProduct(int type) {
        if (type == 1) {
            return new ConcreteProductA();
        } else if (type == 2) {
            return new ConcreteProductB();
        }
        return nullptr;
    }
};

int main() {
    Product* productA = SimpleFactory::createProduct(1);
    Product* productB = SimpleFactory::createProduct(2);

    productA->operation();  // 输出:Concrete Product A
    productB->operation();  // 输出:Concrete Product B

    delete productA;
    delete productB;

    return 0;
}

4.2 工厂方法模式示例

// 抽象产品
class Product {
public:
    virtual void operation() = 0;
};

// 具体产品 A
class ConcreteProductA : public Product {
public:
    void operation() override {
        std::cout << "Concrete Product A" << std::endl;
    }
};

// 具体产品 B
class ConcreteProductB : public Product {
public:

    void operation() override {
        std::cout << "Concrete Product B" << std::endl;
    }
};

// 抽象工厂类
class Factory {
public:
    virtual Product* createProduct() = 0;
};

// 具体工厂 A
class ConcreteFactoryA : public Factory {
public:
    Product* createProduct() override {
        return new ConcreteProductA();
    }
};

// 具体工厂 B
class ConcreteFactoryB : public Factory {
public:
    Product* createProduct() override {
        return new ConcreteProductB();
    }
};

int main() {
    Factory* factoryA = new ConcreteFactoryA();
    Factory* factoryB = new ConcreteFactoryB();

    Product* productA = factoryA->createProduct();
    Product* productB = factoryB->createProduct();

    productA->operation();  // 输出:Concrete Product A
    productB->operation();  // 输出:Concrete Product B

    delete factoryA;
    delete factoryB;
    delete productA;
    delete productB;

    return 0;
}

4.3 抽象工厂模式示例

// 抽象产品 A
class AbstractProductA {
public:
    virtual void operationA() = 0;
};

// 具体产品 A1
class ConcreteProductA1 : public AbstractProductA {
public:
    void operationA() override {
        std::cout << "Concrete Product A1" << std::endl;
    }
};

// 具体产品 A2
class ConcreteProductA2 : public AbstractProductA {
public:
    void operationA() override {
        std::cout << "Concrete Product A2" << std::endl;
    }
};

// 抽象产品 B
class AbstractProductB {
public:
    virtual void operationB() = 0;
};

// 具体产品 B1
class ConcreteProductB1 : public AbstractProductB {
public:
    void operationB() override {
        std::cout << "Concrete Product B1" << std::endl;
    }
};

// 具体产品 B2
class ConcreteProductB2 : public AbstractProductB {
public:
    void operationB() override {
        std::cout << "Concrete Product B2" << std::endl;
    }
};

// 抽象工厂类
class AbstractFactory {
public:
    virtual AbstractProductA* createProductA() = 0;
    virtual AbstractProductB* createProductB() = 0;
};

// 具体工厂 1
class ConcreteFactory1 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ConcreteProductA1();
    }

    AbstractProductB* createProductB() override {
        return new ConcreteProductB1();
    }
};

// 具体工厂 2
class ConcreteFactory2 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ConcreteProductA2();
    }

    AbstractProductB* createProductB() override {
        return new ConcreteProductB2();
    }
};

int main() {
    AbstractFactory* factory1 = new ConcreteFactory1();
    AbstractFactory* factory2 = new ConcreteFactory2();

    AbstractProductA* productA1 = factory1->createProductA();
    AbstractProductB* productB1 = factory1->createProductB();

    AbstractProductA* productA2 = factory2->createProductA();
    AbstractProductB* productB2 = factory2->createProductB();

    productA1->operationA();  // 输出:Concrete Product A1
    productB1->operationB();  // 输出:Concrete Product B1

    productA2->operationA();  // 输出:Concrete Product A2
    productB2->operationB();  // 输出:Concrete Product B2

    delete factory1;
    delete factory2;
    delete productA1;
    delete productB1;
    delete productA2;
    delete productB2;

    return 0;
}

以上代码示例分别演示了简单工厂模式、工厂方法模式和抽象工厂模式的用法,希望能帮助读者更好地理解和应用这三种工厂模式。使用设计模式可以使我们的代码更加灵活、易于维护,并遵循面向对象设计的一些重要原则。

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

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

相关文章

【Spring Boot系列】-Spring Boot过滤器Filter

【Spring Boot系列】-Spring Boot过滤器Filter 文章目录 【Spring Boot系列】-Spring Boot过滤器Filter一、概述二、Filter&#xff08;过滤器&#xff09;数据流程三、Spring Boot 过滤器生命周期四、使用注解方式实现过滤器(WebFilter)4.1. 在springboot 启动类添加该注解Ser…

JAVA大神必备,IDEA自带的JVM监控神器

前言 开发阶段实时监测&#xff0c;自己的JVM信息&#xff0c;实时可视化 Hotspot JVM 垃圾回收监控工具, 支持查看本地和远程JVM进程, 支持G1 and ZGC算法。 插件安装 在线安装 IntelliJ IDEA 可通过在线安装的方式&#xff0c;安装插件 JDK VisualGC&#xff0c;安装步骤: …

过程:从虚拟机上添加 git 并成功提交到 GitLab 的全过程

Ⅰ、准备工作&#xff1a; 1、Git 查看&#xff1a; 其一、命令&#xff1a;git --version // 此时就能在虚拟机环境下看到 git 的版本为: git version 2.41.0 其二、如何在虚拟机上安装 git &#xff1a; A、命令 &#xff1a; sudo apt-get install git B、然后再输入虚…

JavaScript |(三)内建对象 | 数组 | string对象 | 尚硅谷JavaScript基础实战

学习来源&#xff1a;尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版 文章目录 &#x1f4da;数组&#x1f407;数组介绍⭐️数组&#xff08;Array&#xff09;⭐️基本操作⭐️数组的字面量 &#x1f407;数组中的常用方法⭐️push()⭐️pop()⭐️unshift()⭐️shif…

微信小程序wx.getlocation接口权限申请总结

先附上申请通过截图 插播内容&#xff1a;可代开通&#xff0c;保证通过。wx.getLocation接口&#xff08;获取当前的地址位置&#xff09; qq&#xff1a; 308205428 如何申请 当申请微信小程序的wx.getLocation接口权限时&#xff0c;你可以…

yolov8-制作数据集,数据集格式转换(yolo格式-voc格式)附完整代码

yolo训练时可使用的数据集格式为yolo格式以及voc格式&#xff0c; voc格式的数据集在训练时需要先转换为yolo格式&#xff0c;然后根据自己的数据集的位置更改yaml配置文件的文件路径即可。基于目前对Yolo系列训练模型的讲解已经很全面&#xff0c;所以本文主要讲解yolo数据集与…

记录 FreeRTOS 信号量 的简单用法

FreeRTOS 信号量 最简单的应用场景是 两个任务间的同步 &#xff0c;这里以 二值信号量 Binary Semaphore为例 用法 &#xff1a; 1&#xff0c;定义与 创建 /* Definitions for myBinarySem01 */ osSemaphoreId_t myBinarySem01Handle; const osSemaphoreAttr_t myBinarySe…

c++类与对象详解

c类与对象详解 对象类方法自定义类型类的特性this类的六个默认成员函数static成员友元内部类 对象 在C中&#xff0c;对象是类的实例。定义对象的语法为&#xff1a; <class_name> object_name;其中&#xff0c;class_name 是定义类时指定的类名&#xff0c;object_nam…

二分查找【Java算法】

文章目录 1. 概念2. 思路3. 代码实现 1. 概念 二分查找又叫折半查找&#xff0c;要求待查找的序列有序&#xff0c;每次取中间位置的值与待查关键字比较&#xff0c;如果待查关键字比中间位置的值小&#xff0c;则在前半部分循环这个查找的过程&#xff0c;反之&#xff0c;在后…

7_分类算法—逻辑回归

文章目录 逻辑回归&#xff1a;1 Logistic回归&#xff08;二分类问题&#xff09;1.1 sigmoid函数1.2 Logistic回归及似然函数&#xff08;求解&#xff09;1.3 θ参数求解1.4 Logistic回归损失函数1.5 LogisticRegression总结 2 Softmax回归&#xff08;多分类问题&#xff0…

单元测试之 - Review一个微服务的单元测试

这里以github上一个microservice的demo代码为例&#xff0c;来看看如何为一个完整的服务编写单元测试。具体代码如下所示&#xff0c;我们重点查看一下catalog和customer&#xff0c;order中的单元测试有哪些。 首先来看catalog服务的单元测试,这个服务下面主要编写了CatalogWe…

时序数据异常检测算法

引言 异常检测的场景很多&#xff0c;例如&#xff1a;硬件的故障检测、流量的异常点的检测等场景。针对时间序列类数据的异常检测算法也有很多&#xff0c;业界比较流行的比如普通的统计学习方法–3σ原则和箱线图识别数据离群点&#xff0c;它利用检测点偏移量来检测出异常。…

Michael.W基于Foundry精读Openzeppelin第19期——EnumerableSet.sol

Michael.W基于Foundry精读Openzeppelin第19期——EnumerableSet.sol 0. 版本0.1 EnumerableSet.sol 1. 目标合约2. 代码精读2.1 结构体Set2.1.1 _contains(Set storage set, bytes32 value) && _length(Set storage set) && _at(Set storage set, uint256 inde…

Linux的基本指令(2)

指令1&#xff1a;man 作用&#xff1a;可以查询linux指令语法内容。 格式&#xff1a; man 指令 安装man指令&#xff1a; yum install -y man-pages 例如&#xff1a; 查询 指令 ls 的语法内容。 man ls 查询 fork 指令的语法内容。 man fork 在man中存在9个手册&…

2023年08月编程语言流行度排名

点击查看最新编程语言流行度排名&#xff08;每月更新&#xff09; 2023年08月编程语言流行度排名 编程语言流行度排名是通过分析在谷歌上搜索语言教程的频率而创建的 一门语言教程被搜索的次数越多&#xff0c;大家就会认为该语言越受欢迎。这是一个领先指标。原始数据来自…

word转pdf怎么转?几种常用方法分享

word转pdf怎么转&#xff1f;在日常工作和学习中&#xff0c;将Word文档转换为PDF格式是一项必要的任务。不仅可以保证文档的格式不变&#xff0c;还可以防止文档被他人篡改。但是&#xff0c;Word文档并不是所有人都能够轻松打开和编辑的&#xff0c;而PDF文件则可以在各种设备…

Python---Matplotlib

文章目录 1.什么是matplotlib?2.实现一个简单的matplotlib绘图3.matplotlib图像结构4.matplotlib基础绘图多个坐标系显示— plt.subplots(面向对象的画图方法) 5.常见图形种类 1.什么是matplotlib? Matplotlib是一个用于绘制数据可视化图形的Python库。它是一个广泛使用的数…

SystemVerilog scheduler

文章目录 简介调度器simulation regionPreponed regionActive regionInactive regionNBA(Non-blocking Assignment Events region)Observed regionReactive regionRe-Inactive Events regionRe-NBA RegionPostponed Region PLI region:Pre-active regionPre-NBA regionPost-NBA…

锁相环是锁住正弦电压波形的0度位置还是90度位置,欢迎大家参与讨论?

文章目录 最近做三相PFC控制电源开发&#xff0c;里面使用到锁相环&#xff0c;跟大家一起讨论一下&#xff0c;锁相环锁的是A,B,C哪一相&#xff0c;是0度位置还是90度位置&#xff1f;讨论区&#xff1a;大家的观点是什么&#xff0c;请投票选择&#xff0c;后续会一起讨论正…

2023年华数杯赛题浅析

2023年华数杯作为与国赛同频的比赛&#xff08;周四6点发题&#xff0c;周日晚8点交卷&#xff09;&#xff0c;也是暑期唯一一个正式比赛。今年的报名队伍已经高达​6000多对。基于这么多的人数进行国赛前队伍的练习&#xff0c;以及​其他用途。为了方便大家跟更好的选题&…