工厂方法模式与抽象工厂模式
工厂方法模式 (Factory Method)
定义: 工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法将类的实例化推迟到子类。
优点:
- 解耦:客户端代码与具体的产品类解耦,只依赖于产品的接口。
- 可扩展性:新增产品只需实现相应的工厂方法,无需修改现有代码。
- 灵活性:可以根据具体需求选择不同的产品。
应用场景:
- 当一个类不知道它所需要的对象的类时。
- 当一个类希望通过子类来指定所创建的对象时。
- 当类的实例化过程非常复杂时。
C++ 示例代码
以下是一个简单的工厂方法模式示例,展示了如何创建不同类型的汽车。
1. 产品接口
首先,我们定义一个汽车的接口。
#include <iostream>
#include <memory>// 产品接口
class Car {
public:virtual void drive() = 0; // 驾驶方法virtual ~Car() = default; // 虚析构函数
};
2. 具体产品
接下来,我们定义具体的汽车类,分别实现 Car 接口。
// 具体产品:轿车
class Sedan : public Car {
public:void drive() override {std::cout << "Driving a Sedan.\n";}
};// 具体产品:SUV
class SUV : public Car {
public:void drive() override {std::cout << "Driving an SUV.\n";}
};
3. 工厂接口
然后,我们定义一个工厂接口,用于创建汽车对象。
// 工厂接口
class CarFactory {
public:virtual std::unique_ptr<Car> createCar() = 0; // 工厂方法virtual ~CarFactory() = default; // 虚析构函数
};
4. 具体工厂
实现具体工厂类,分别创建不同类型的汽车。
// 具体工厂:轿车工厂
class SedanFactory : public CarFactory {
public:std::unique_ptr<Car> createCar() override {return std::make_unique<Sedan>(); // 创建轿车}
};// 具体工厂:SUV工厂
class SUVFactory : public CarFactory {
public:std::unique_ptr<Car> createCar() override {return std::make_unique<SUV>(); // 创建SUV}
};
5. 客户端代码
最后,我们在客户端代码中使用这些工厂。
int main() {// 创建轿车工厂并生产轿车std::unique_ptr<CarFactory> sedanFactory = std::make_unique<SedanFactory>();std::unique_ptr<Car> sedan = sedanFactory->createCar();sedan->drive(); // 输出: Driving a Sedan.// 创建SUV工厂并生产SUVstd::unique_ptr<CarFactory> suvFactory = std::make_unique<SUVFactory>();std::unique_ptr<Car> suv = suvFactory->createCar();suv->drive(); // 输出: Driving an SUV.return 0;
}
总结
在这个示例中,工厂方法模式允许我们通过不同的工厂类创建不同类型的汽车。客户端代码只需要依赖于 CarFactory 和 Car 接口,而不需要了解具体的汽车实现。这种解耦设计提高了代码的灵活性和可维护性,便于未来的扩展。
- 抽象工厂模式
抽象工厂模式 (Abstract Factory)
定义: 抽象工厂模式是一种创建型设计模式,它提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。通过这种方式,抽象工厂模式可以使客户端代码与具体产品的实现解耦。
优点:
- 解耦:客户端不需要依赖具体产品类,可以通过抽象接口进行交互。
- 可扩展性:如果需要增加新的产品,只需实现新的工厂和产品类,无需修改现有代码。
- 一致性:确保产品之间的兼容性和一致性。
应用场景:
- 当系统需要独立于其产品的创建、组合和表示时。
- 当系统需要根据不同的配置来生成一系列相关的产品时。
C++ 示例代码
以下是一个简单的抽象工厂模式示例,展示了如何创建不同类型的家具(椅子和沙发)。
1. 产品接口
首先,我们定义椅子和沙发的接口。
#include <iostream>
#include <memory>// 椅子接口
class Chair {
public:virtual void sitOn() = 0; // 坐下的方法virtual ~Chair() = default; // 虚析构函数
};// 沙发接口
class Sofa {
public:virtual void lieOn() = 0; // 躺下的方法virtual ~Sofa() = default; // 虚析构函数
};
2. 具体产品
接下来,我们定义具体的椅子和沙发类。
// 具体产品:现代椅子
class ModernChair : public Chair {
public:void sitOn() override {std::cout << "Sitting on a Modern Chair.\n";}
};// 具体产品:古典椅子
class VictorianChair : public Chair {
public:void sitOn() override {std::cout << "Sitting on a Victorian Chair.\n";}
};// 具体产品:现代沙发
class ModernSofa : public Sofa {
public:void lieOn() override {std::cout << "Lying on a Modern Sofa.\n";}
};// 具体产品:古典沙发
class VictorianSofa : public Sofa {
public:void lieOn() override {std::cout << "Lying on a Victorian Sofa.\n";}
};
3. 抽象工厂
然后,我们定义一个抽象工厂接口,用于创建椅子和沙发。
// 抽象工厂接口
class FurnitureFactory {
public:virtual std::unique_ptr<Chair> createChair() = 0; // 创建椅子的方法virtual std::unique_ptr<Sofa> createSofa() = 0; // 创建沙发的方法virtual ~FurnitureFactory() = default; // 虚析构函数
};
4. 具体工厂
实现具体工厂类,分别创建现代和古典家具。
// 具体工厂:现代家具工厂
class ModernFurnitureFactory : public FurnitureFactory {
public:std::unique_ptr<Chair> createChair() override {return std::make_unique<ModernChair>(); // 创建现代椅子}std::unique_ptr<Sofa> createSofa() override {return std::make_unique<ModernSofa>(); // 创建现代沙发}
};// 具体工厂:古典家具工厂
class VictorianFurnitureFactory : public FurnitureFactory {
public:std::unique_ptr<Chair> createChair() override {return std::make_unique<VictorianChair>(); // 创建古典椅子}std::unique_ptr<Sofa> createSofa() override {return std::make_unique<VictorianSofa>(); // 创建古典沙发}
};
5. 客户端代码
最后,我们在客户端代码中使用这些工厂。
int main() {// 创建现代家具工厂std::unique_ptr<FurnitureFactory> modernFactory = std::make_unique<ModernFurnitureFactory>();std::unique_ptr<Chair> modernChair = modernFactory->createChair();std::unique_ptr<Sofa> modernSofa = modernFactory->createSofa();modernChair->sitOn(); // 输出: Sitting on a Modern Chair.modernSofa->lieOn(); // 输出: Lying on a Modern Sofa.// 创建古典家具工厂std::unique_ptr<FurnitureFactory> victorianFactory = std::make_unique<VictorianFurnitureFactory>();std::unique_ptr<Chair> victorianChair = victorianFactory->createChair();std::unique_ptr<Sofa> victorianSofa = victorianFactory->createSofa();victorianChair->sitOn(); // 输出: Sitting on a Victorian Chair.victorianSofa->lieOn(); // 输出: Lying on a Victorian Sofa.return 0;
}
总结
在这个示例中,抽象工厂模式允许我们通过不同的工厂类创建不同类型的家具(椅子和沙发)。客户端代码只依赖于 FurnitureFactory 和产品接口,而不需要了解具体的家具实现。这种解耦设计提高了代码的灵活性和可维护性,便于未来的扩展和修改。通过这种模式,可以确保创建的家具产品之间的一致性和相互适配。
相关文章:
工厂方法模式与抽象工厂模式
工厂方法模式 (Factory Method) 定义: 工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法将类的实例化推迟到子类。 优点: 解耦:客户端代码与具体的产品类解耦…...
「Math」初等数学知识点大纲(占位待处理)
✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…...
百元高性价比头戴式降噪耳机选哪款?四款平价性价比品牌别错过!
随着科技的发展,现在的头戴式耳机真的是越来越多样了,很多的朋友在选购耳机的时候,不知道哪一款头戴式耳机的性价比较高,究竟百元高性价比头戴式降噪耳机选哪款?身为一名数码爱好者,这里就给大家推带来四款…...
vue3 setup写不写到标签上的区别
在vue3种setup的写法,可以单独写setup()也可以写到script标签中,当然我们推荐后面这种 他的好处有很多,代码也简洁很多。1、属性和方法无需return,可直接使用 /*原先*/ <script> import { defineComponent } from "v…...
【论文解读】EdgeYOLO:一种边缘实时目标检测器(附论文地址)
论文地址:https://arxiv.org/pdf/2302.07483 这篇文章的标题是《EdgeYOLO: An Edge-Real-Time Object Detector》,由中国北京理工大学的Shihan Liu、Junlin Zha、Jian Sun、Zhuo Li和Gang Wang共同撰写。这篇论文提出了一个基于最新YOLO框架的高效、低复…...
xlwings,让excel飞起来!
excel已经成为必不可少的数据处理软件,几乎天天在用。python有很多支持操作excel的第三方库,xlwings是其中一个。 关于xlwings xlwings开源免费,能够非常方便的读写Excel文件中的数据,并且能够进行单元格格式的修改。 xlwings还…...
C语言学习,标准库 <stddef.h>
<stddef.h> C 标准库中头文件,它定义了一些常用的类型定义和宏。这些定义通常用于指针操作、数组处理和其他需要固定大小数据类型的场合。 size_t: 这是一个无符号整数类型,用于表示对象的大小(以字节为单位)。…...
PyQt5实战——操作台打印重定向,主界面以及stacklayout使用(四)
个人博客:苏三有春的博客 系类往期文章: PyQt5实战——多脚本集合包,前言与环境配置(一) PyQt5实战——多脚本集合包,UI以及工程布局(二) PyQt5实战——多脚本集合包,程序…...
React + Vite + TypeScript + React router项目搭建教程
一、创建项目 运行项目 二、目录结构 项目目录: ├─node_modules //第三方依赖 ├─public //静态资源(不参与打包) └─src├─assets //静态资源├─components //组件├─config //配置├─http //请求方法封装├─layout //页面…...
【ShuQiHere】️ 如何启用 SSH 服务
🛠️ 如何启用 SSH 服务 目录 基础概念 🌱检查是否已安装 SSH 服务 🔍在不同操作系统上安装 SSH 服务 💻 LinuxWindows 11macOS 启动和启用 SSH 服务 🚀配置防火墙以允许 SSH 连接 🔥配置 SSH 服务&#…...
【自动化测试】APP UI 自动化(安卓)-本地环境搭建
一、软件准备及版本介绍 软件版本JAVA-SDK1.8.0_181 python 3.10.10 Android SDK Tools 下最新版本即可,无特殊要求 PyCharm 2023.3.5(下最新版本即可,无特殊要求) 二、安装步骤及环境变量配置 2.1 Java安装及配置 1&am…...
java毕业设计之基于Bootstrap的常州地方旅游管理系统的设计与实现(springboot)
项目简介 基于Bootstrap的常州地方旅游管理系统的设计与实现有下功能: 基于Bootstrap的常州地方旅游管理系统的设计与实现的主要使用者分为用户功能模块和管理员功能模块两大部分,用户可查看景点信息、景点资讯等,注册登录后可进行景点订票…...
《机甲崛起》
第一章:觉醒 在遥远的未来,地球的面貌已被人类科技彻底改变。蓝天被高耸的摩天大楼和闪烁的飞行器撕裂,城市的光辉仿佛能照亮整个星球。然而,繁华背后隐藏着深重的危机:生态环境的恶化、资源的匮乏,已成为…...
Windows10:Linux Reader
Linux Reader Access files and folders on Ext, UFS, HFS, ReiserFS, or APFS file systems from Windows DiskInternals 发布的 Linux Reader 是一款能在 Windows 系统环境下读取 Linux 分区文件的免费软件,提供了资源管理器式的浏览模式。它使用只读模式挂载 L…...
一、k8s快速入门之学习Kubernetes组件基础
一、三个容器管理器平台 Apache MESOS 开源的分布式资源管理框架,被推特选为基础平台,2019年推特换位k8s,MESOS最新版可以在MESOS上管理k8sDOCKER SWARM docker总部发行的,实现docker的集群方案,和docker捆版一起&…...
PostgreSQL 到 PostgreSQL 数据迁移同步
简述 PostgreSQL 是一个历史悠久且广泛使用的数据库,不仅具备标准的关系型数据库能力,还具有相当不错的复杂 SQL 执行能力。用户常常会将 PostgreSQL 应用于在线事务型业务,以及部分数据分析工作,所以 PostgreSQL 到 PostgreSQL …...
RestTemplate 常用方法(提供了多种方法来发送 HTTP 请求)
RestTemplate 是 Spring 框架中用于同步客户端 HTTP 请求的一个类,它提供了多种方法来发送 HTTP 请求。以下是一些常用的 RestTemplate 方法及其代码案例: 1.postForObject() 该方法用于发送 POST 请求,并期望返回一个对象。以下是一个使用…...
常量和变量
常量 常量是指在程序中使用的一些具体的数、字符。在程序运行过程中,其值不能被更改。如123,145.88,m,TRUE等。常量,用于记录程序中不可更改的数据。 分类 1、整型常量,表示整数的常量。 表示形式: 1)十进制形…...
Go语言的使用
在安装Go和配置镜像时,可以根据操作系统和网络环境来选择适合的步骤。以下是详细的安装步骤和镜像配置: 1. 安装Go 1.1 通过官方下载 访问 Go的官方下载页面 下载适合操作系统的安装包(Windows、macOS 或 Linux)。安装包下载完…...
详解CRC校验原理以及FPGA实现
文章目录 一、什么是CRC校验?二、实现CRC校验原理以及步骤2.1 用多项式表示二元码数据2.2 选择一个生成多项式作为校验2.3 计算CRC校验码 三、CRC判断数据是否错误的原理以及步骤3.1 将收到的数据与生成多项式求余3.2 数据发生错误再进行CRC校验判断 四、FPGA实现CR…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
