工厂模式详解与应用场景

摘要:

工厂模式是一种常见的设计模式,它可以帮助我们在面向对象的程序设计中更好地组织和管理对象的创建过程。本文将详细介绍工厂模式的概念、三种常见的工厂模式应用场景,并提供高质量的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;
}

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

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

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

相关文章

【练】创建两个线程:其中一个线程拷贝图片的前半部分,另一个线程拷贝后半部分

方法一&#xff1a; 先在主函数创建并清空拷贝的目标文件&#xff0c;再创建两个线程&#xff0c;在两个线程内部同时打开要读取的文件以及要拷贝的目标文件&#xff08;两个线程不共用同一份资源&#xff09;。 使用到的函数&#xff1a; 标准IO函数&#xff08;fprintf&…

C++模板

目录 一.泛型编程 二.模板 1.函数模板 1.1函数模板格式&#xff1a; 1.2函数模板的原理 1.3 函数模板的实例化 隐式实例化 显式实例化 &#xff1a; 模板参数的匹配原则&#xff1a; 2.类模板 2.1类模板格式 一.泛型编程 如何实现一个通用的交换函数呢&#xff1f;…

主动带宽控制工具

停机和带宽过度使用是任何组织都无法避免的两个问题。随着企业采用 BYOD 文化&#xff0c;通过网络的流量负载可能很重&#xff0c;导致网络拥塞并使网络容易受到网络攻击。为了解决这个问题&#xff0c;企业需要全面的监控策略来保护网络&#xff0c;当看似大量的流量进入网络…

C++学习——模板

目录 &#x1f349;一&#xff1a;什么是模板 &#x1f34e;二&#xff1a;普通模板的定义 &#x1f34d;三&#xff1a;类模板的定义 &#x1f34c;四&#xff1a;模板的实例化 &#x1f347;1.当普通模板定义存在可修改返回值产生的分歧 &#x1f348;2&#xff1a;类模板实例…

一文读透时区和时间戳以及基于Java的操作

重要概念 1. UTC 和 UTC8 UTC 是世界标准时间&#xff0c; UTC8 是东八区标准时间&#xff0c;中国就属于东八区&#xff0c; 也就是北京时间。 8 就是加8个小时。 时区的划分图示如下&#xff1a; 也就是说&#xff1a; 假如现在是UTC时间是 2023-08-08 01:00:00 &#xff0…

MySQL数据库——多表操作

文章目录 前言多表关系一对一关系一对多/多对一关系多对多关系 外键约束创建外键约束插入数据删除带有外键约束的表的数据删除外键约束 多表联合查询数据准备交叉连接查询内连接查询外连接查询左外连接查询右外连接查询满外连接查询 子查询子查询关键字ALL 关键字ANY 和 SOME 关…

k8s kubeadm命令升级集群 从1.17升级到1.18

k8s kubeadm命令升级集群 从1.17升级到1.18 大纲 注意事项master节点执行升级命令master节点和node节点执行命令 注意事项 目标当前线上k8s集群版本是k8s1.17 想把k8s升级到1.18。注意k8s不能跨版本升级例如k8s1.17不能直接升级到k8s1.19&#xff0c;需要先升级到1.18才后向…

【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

dubbo的高可用

1、zookeeper宕机与dubbo直连 现象&#xff1a;zookeeper注册中心宕机&#xff0c;还可以消费dubbo暴露的服务。 原因&#xff1a; 健壮性 &#xff08;1&#xff09;监控中心宕掉不影响使用&#xff0c;只是丢失部分采样数据. &#xff08;2&#xff09;数据库宕掉后&#x…

springboot访问请求404的原因

是记录&#xff0c;可能出现错误 可能出现的原因 1.你请求的URL路径不对,比如说你请求的路径是/usr/list,GET方法,但是你UserController上面的RequestMapping是这个样子:RequestMapping(“user”)&#xff0c;有可能哈 2.前端的请求时GET方法&#xff0c;后端对应的处理函数的方…

C++ 指针数组

如果一个数组的每个元素都是指针变量&#xff0c;这个数组就是指针数组。指针数组的每个元素都必须是同一类型的指针。 1.一维指针数组 声明一维指针数组的语法形式&#xff1a; 数据类型*数组名[下标表达式];下标表达式指出数组元素的个数&#xff0c;数据类型确定每个元素…

Kafka3.0.0版本——生产者如何提高吞吐量

目录 一、生产者提高吞吐量参数设置二、产者提高吞吐量代码示例 一、生产者提高吞吐量参数设置 batch.size&#xff1a;设置批次大小&#xff0c;默认16klinger.ms&#xff1a;设置等待时间&#xff0c;修改为5-100msbuffer.memory&#xff1a;设置缓冲区大小&#xff0c; 默认…

信号槽中的函数重载

信号槽中的函数重载 QT4的方式QT5的方式函数指针重载函数QT5信号函数重载解决方案 总结 QT4的方式 Qt4中声明槽函数必须要使用 slots 关键字, 不能省略。 信号函数&#xff1a; 槽函数&#xff1a; mainwondow: cpp文件&#xff1a; #include "mainwindow.h"…

快速部署外卖系统:利用现代工具简化开发流程

在竞争激烈的外卖市场中&#xff0c;快速部署高效稳定的外卖系统是餐饮企业成功的关键之一。本文将介绍如何利用现代工具简化外卖系统的开发流程&#xff0c;并附带代码示例&#xff0c;帮助开发者快速搭建功能完备、用户友好的外卖平台。 1. 简介 在外卖业务快速增长的背景…

使用express搭建后端服务

目录 1 创建工程目录2 初始化3 安装express依赖4 启动服务5 访问服务总结 上一篇我们利用TDesign搭建了前端服务&#xff0c;现在的开发讲究一个前后端分离&#xff0c;后端的话需要单独搭建服务。后端服务的技术栈还挺多&#xff0c;有java、php、python、nodejs等。在众多的技…

稍微深度踩坑haystack + whoosh + jieba

说到django的全文检索&#xff0c;网上基本推荐的都是 haystack whoosh jieba 的方案。 由于我的需求对搜索时间敏感度较低&#xff0c;但是要求不能有数据的错漏。 但是没有调试的情况下&#xff0c;搜索质量真的很差&#xff0c;搞得我都想直接用Like搜索数据库算了。 但是…

排序八卦炉之冒泡、快排

文章目录 1.冒泡排序1.1代码实现1.2复杂度 2.快速排序2.1人物及思想介绍【源于百度】2.2hoare【霍尔】版本1.初识代码2.代码分析3.思其因果 3.相关博客 1.冒泡排序 1.1代码实现 //插入排序 O(N)~O(N^2) //冒泡排序 O(N)~O(N^2) //当数据有序 二者均为O(N) //当数据接近有序或…

什么是 webpack?

Webpack 介绍 什么是 webpack&#xff1f; :::tip 官方描述 webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。当 webpack 处理应用程序时&#xff0c;它会在内部从一个或多个入口点构建一个 依赖图(dependency graph)&#xff0c;然后将你项目中所需的每一个…

第四章 数据库安全性

问题的提出 &#xff08;1&#xff09;数据库的一大特点是数据可以共享 &#xff08;2&#xff09;数据共享必然带来数据库的安全性问题 &#xff08;3&#xff09;数据库系统中的数据共享不能是无条件的共享 这就引发了数据库安全性问题 1.数据库安全性概述 数据库的安全性…

MySQL日志——查询日志

1.查询日志 show variables like %general%;修改mysql的配置文件 /etc/my.cnf文件&#xff0c;添加如下内容&#xff1a; #该选项用来开启查询日志&#xff0c;可选值&#xff1a;0或者1&#xff1b;0代表关闭&#xff0c;1代表开启 general_log1 #设置日志的文件名&#xff0…