设计模式12:抽象工厂模式
系列总链接:《大话设计模式》学习记录_net 大话设计-CSDN博客
参考:
C++设计模式:抽象工厂模式(风格切换案例)_c++ 抽象工厂-CSDN博客
1.概念
抽象工厂模式(Abstract Factory Pattern)是软件设计模式中的一种创建型模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。这种模式强调的是家族的概念,即一个工厂可以生产出一整套兼容的产品。
2.结构与实现
结构:
- 抽象工厂 (Abstract Factory)
定义了一个创建一组相关或相互依赖对象的接口,但不负责这些对象的具体类。它声明了一组用于创建不同产品的方法,但并不实现它们。
- 具体工厂 (Concrete Factory)
实现了抽象工厂接口,负责创建具体的产品对象。每个具体工厂对应一个特定的产品族,并能够创建该族中的所有产品。
- 抽象产品 (Abstract Product)
为每类产品定义了一个接口,具体产品的类实现这个接口。不同的产品族可能有不同的抽象产品接口。
- 具体产品 (Concrete Product)
由具体工厂创建的对象,实现了抽象产品接口。每个具体产品属于一个特定的产品族,并且与同一族中的其他产品兼容。
- 客户端代码 (Client Code)
客户端代码使用抽象工厂和抽象产品接口来操作对象,而不直接引用具体工厂或具体产品的类。这使得客户端代码可以独立于具体的产品实现。
通过上述结构,抽象工厂模式提供了一种方式来创建一系列相关的对象,而无需指定它们的具体类。这种方式不仅提高了代码的灵活性和可维护性,还使得添加新的产品族变得更为简单,因为只需要增加一个新的具体工厂和相应的产品实现即可。
实现:
#ifndef ABSTRACTFACTORY_H
#define ABSTRACTFACTORY_H//抽象产品类
class IProductPhone
{
public:IProductPhone() {}virtual void showPhoneType(){}
};//具体产品类
class Piphone : public IProductPhone
{
public:Piphone() {}void showPhoneType(){qDebug() << "i am iphone";}
};class PXiaomi : public IProductPhone
{
public:PXiaomi() {}void showPhoneType(){qDebug() << "i am xiaomi";}
};//抽象工厂类
class IFactory
{
public:IFactory() {}virtual IProductPhone* createPhone(){}
};//具体工厂类
class IphoneFactory : public IFactory
{
public:IphoneFactory(){}IProductPhone* createPhone(){qDebug() << "create a iphone"; return new Piphone;}
};class XiaomiFactory : public IFactory
{
public:XiaomiFactory(){}IProductPhone* createPhone(){qDebug() << "create a xiaomi"; return new PXiaomi;}
};#endif // ABSTRACTFACTORY_H
使用:
#include <QCoreApplication>
#include <QDebug>#include "abstractFactory.h"int main(int argc, char *argv[])
{IFactory* ifact=nullptr;IProductPhone* iprod = nullptr;QString currentFact = "xiaomi";if("xiaomi" == currentFact){ifact = new XiaomiFactory;}else if("iphone" == currentFact){ifact = new IphoneFactory;}iprod = ifact->createPhone();iprod->showPhoneType();return 0;
}
3.应用
-
数据库访问层(DAL)
当应用程序需要支持多种数据库后端时,可以为每种数据库类型定义一个工厂,用于创建相应的数据访问对象(DAO)。这样可以轻松切换数据库而无需修改业务逻辑代码。如:
MySQLFactory创建适用于 MySQL 数据库的数据访问对象。OracleFactory创建适用于 Oracle 数据库的数据访问对象。
4.优缺点及适用环境
优点:
- 将客户端代码与具体的产品实现解耦:
客户端只需要依赖于抽象接口,而不需要知道具体的类。这提高了代码的灵活性和可维护性。
- 易于添加新的产品族:
只需创建一个新的具体工厂和相关的产品实现,即可扩展系统支持新的产品族,符合“开闭原则”。
- 确保同一产品族的产品一起使用:
确保从同一个工厂创建的产品是兼容的,避免了不同产品族之间的不一致问题。
- 简化了复杂的对象创建逻辑:
将对象创建逻辑集中到工厂中,使得客户端代码更加简洁,减少了重复代码。
缺点:
- 增加了系统的复杂度:
引入了额外的接口和类,可能会使系统更难理解,特别是对于小型项目或简单需求来说。
- 难以添加新产品:
如果需要添加一个新的产品类型(而不是新的产品族),则必须修改所有工厂类,违反了“开闭原则”。
- 可能导致过度设计:
在一些场景下,可能没有必要引入这么复杂的模式,导致设计过于复杂,增加不必要的开发和维护成本。
适用环境:
- 当系统需要独立于其产品的创建、组合和表示时:
特别是当你希望提供一个框架或库,但不想暴露内部的具体实现细节。
- 当一个系统要由多个产品系列中的一个来配置时:
比如多平台UI库、多数据库后端的支持等,每个系列有自己的一组相关联的对象。
- 当系统需要支持插件或模块化扩展时:
插件可以提供自己的工厂实现,以创建特定功能和服务,而不影响核心系统。
- 当需要频繁切换不同产品族时:
例如,在运行时根据用户选择或其他条件动态地改变产品族。
总结来说,抽象工厂模式非常适合那些需要处理多个产品系列的应用程序,并且这些系列中的对象需要保持一致性。它有助于提高代码的灵活性和可维护性,但也可能带来额外的复杂性和设计上的挑战。在决定是否采用此模式时,应权衡项目的实际需求和复杂度。
相关文章:
设计模式12:抽象工厂模式
系列总链接:《大话设计模式》学习记录_net 大话设计-CSDN博客 参考: C设计模式:抽象工厂模式(风格切换案例)_c 抽象工厂-CSDN博客 1.概念 抽象工厂模式(Abstract Factory Pattern)是软件设计…...
论文学习——多种变化环境下基于多种群进化的动态约束多目标优化
论文题目:Multipopulation Evolution-Based Dynamic Constrained Multiobjective Optimization Under Diverse Changing Environments 多种变化环境下基于多种群进化的动态约束多目标优化(Qingda Chen , Member, IEEE, Jinliang Ding , Senior Member, …...
Jenkins参数化构建详解(This project is parameterized)
本文详细介绍了Jenkins中不同类型的参数化构建方法,包括字符串、选项、多行文本、布尔值和git分支参数的配置,以及如何使用ActiveChoiceParameter实现动态获取参数选项。通过示例展示了传统方法和声明式pipeline的语法 文章目录 1. Jenkins的参数化构建1…...
Cerebras 推出 CePO,填补推理与规划能力的关键空白
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
广东省食品销售中高级题库及答案
1.有关食品安全标准的说法正确的是(C)。 A.鼓励性标准 B.推荐性标准 C.强制性标准 D.引导性标准 2.食品经营许可证载明的许可事项发生变化的,食品经营者应当在变化后(D)个工作日内向原发证的食品药品监督管理部门申请变更经营许可。 A.3 B.5 C.7 D.10 3.食品销售经营者对食品…...
JAVA基础-深入理解Java内存模型(一)-- 重排序与先行发生原则(happens-before)
深入理解Java内存模型(一)-- 重排序 很棒的一个关于Java内存模型系列文章,首先感谢作者,转载自深入理解java内存模型系列文章 ,为了方便阅读,做了一些内容整合和重排版。 提纲 Java线程之间的通信对程序…...
【Lambda】java之lambda表达式stream流式编程操作集合
java之lambda表达式&stream流式编程操作集合 1 stream流概念1.1 中间操作1.1.1 无状态操作1.1.2 有状态操作 1.2 终端操作1.2.1 非短路操作1.2.2 短路操作 2 steam流的生成2.1 方式一:数组转为stream流2.2 方式二:集合转为steam流2.3 方式三…...
家具购物小程序+php
基于微信小程序的家具购物小程序的设计与实现 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的家具购物小程序的设计与实现的开发全过程。通过分析基于微信小程序的家具购物小程序的设计与实…...
【GIS教程】使用GDAL-Python将tif转为COG并在ArcGIS Js前端加载-附完整代码
目录 一、数据格式 二、COG特点 三、使用GDAL生成COG格式的数据 四、使用ArcGIS Maps SDK for JavaScript加载COG格式数据 一、数据格式 COG(Cloud optimized GeoTIFF)是一种GeoTiff格式的数据。托管在 HTTP 文件服务器上,可以代替geose…...
VB.net进行CAD二次开发(二)与cad交互
开发过程遇到了一个问题:自制窗口与控件与CAD的交互。 启动类,调用非模式窗口 Imports Autodesk.AutoCAD.Runtime Public Class Class1 //CAD启动界面 <CommandMethod("US")> Public Sub UiStart() Dim myfrom As Form1 New…...
【NLP 11、Adam优化器】
祝你先于春天, 翻过此间铮铮山峦 —— 24.12.8 一、Adam优化器的基本概念 定义 Adam(Adaptive Moment Estimation)是一种基于梯度的优化算法,用于更新神经网络等机器学习模型中的参数。它结合了动量法(Momentum&…...
51单片机应用开发(进阶)---串口接收字符命令
实现目标 1、巩固UART知识; 2、掌握串口接收字符数据; 3、具体实现目标:(1)上位机串口助手发送多字符命令,单片机接收命令作相应的处理(如:openled1 即打开LED1;closeled1 即关…...
redis 怎么样删除list
在 Redis 中,可以使用以下方法删除列表或列表中的元素: 1. 删除整个列表 使用 DEL 命令删除一个列表键: DEL mylist这个命令会删除键 mylist 及其值(无论 mylist 是一个列表还是其他类型的键)。 2. 删除列表中的部分…...
【数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
目录😋 任务描述 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:实现快速排序算法。 测试说明 平台会对你编写的代码进行测试: 测试输入示例: 10 6 8 7 9 0 1 3 2 4 5 (说明:第一行是元素个数&a…...
npm或yarn包配置地址源
三种方法 1.配置.npmrc 文件 在更目录新增.npmrc文件 然后写入需要访问的包的地址 2.直接yarn.lock文件里面修改地址 简单粗暴 3.yarn install 的时候添加参数 设置包的仓库地址 yarn config set registry https://registry.yarnpkg.com 安装:yarn install 注意…...
STUN服务器用于内网NAT的方案
在内网中部署 STUN 服务器的场景通常用于处理多层 NAT 或内网客户端之间的通信需求,尤其是在大企业或学校等复杂网络环境下。通过 STUN 服务器,可以帮助客户端设备检测和适配 NAT 转换规则,进而支持 WebRTC 或其他实时通信技术的正常运行。 …...
Linux 简单命令总结
1. 简单命令 1.1. ls 列出该目录下的所有子目录与文件,后面还可以跟上一些选项 常用选项: ・-a 列出目录下的所有文件,包括以。开头的隐含文件。 ・-d 将目录象文件一样显示,而不是显示其下的文件。如:ls -d 指定目…...
Vue.js组件开发:提升你的前端工程能力
Vue.js 是一个用于构建用户界面的渐进式框架,它允许开发者通过组件化的方式创建可复用且易于管理的代码。在 Vue.js 中开发组件是一个直观且高效的过程,下面我将概述如何创建和使用 Vue 组件,并提供一些最佳实践。 1. 创建基本组件 首先&am…...
使用 Pandas 读取 JSON 数据的五种常见结构解析
文章目录 引言JSON 数据的五种常见结构1. split 结构2. records 结构3. index 结构4. columns 结构5. values 结构 引言 在日常生活中,我们经常与各种数据打交道,无论是从网上购物的订单信息到社交媒体上的动态更新。JSON(JavaScript Object…...
C++鼠标轨迹算法(鼠标轨迹模拟真人移动)
一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序,它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言,原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势: 模拟…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...
Linux-进程间的通信
1、IPC: Inter Process Communication(进程间通信): 由于每个进程在操作系统中有独立的地址空间,它们不能像线程那样直接访问彼此的内存,所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...
【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...
