Python设计模式 - 抽象工厂模式
定义
抽象工厂模式是一种创建型设计模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
产品等级结构与产品族
为了更好地理解抽象工厂模式,先引入两个概念:
- 产品等级结构:就是产品的继承结构。例如电视机抽象类有A品牌电视机子类和B品牌电视机子类,那么抽象电视机和具体品牌的电视机就构成了一个产品等级结构。
- 产品族:同一个工厂生产的,位于不同产品等级结构中的一组产品。例如海尔工厂生产的海尔电视机、海尔电冰箱就构成了一个产品族。
结构

- 抽象工厂(Abstract Factory):声明一组用于创建一个产品族产品的工厂方法,每个工厂方法对应一种产品。
- 具体工厂(Concrete Factory):实现抽象工厂中的工厂方法,这些方法创建的产品构成了一个产品族,每种产品都位于不同的产品等级结构中。
- 抽象产品(Abstract Product):定义产品对象的接口。
- 具体产品(Concrete Product):实现产品接口的具体产品对象。
应用场景
- 跨平台的产品系列:当需要为不同的平台(如Windows、Mac、Linux)创建一系列相关的产品时,可以使用抽象工厂模式。每个具体工厂类实现工厂方法来创建一个平台的所有产品。例如,跨平台的GUI框架需要针对不同操作系统生成不同风格的按钮、文本框等组件。
- 使用多个产品族:系统中有多于一个的产品族,而每次只使用其中某一个产品族,客户端可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族。例如,窗口中的按钮、文本框可以根据用户的选择按照不同的风格来展示。
优缺点
优点:
- 封装对象创建:抽象工厂模式将一系列相关对象的创建封装在一起,客户端无需关心对象的创建过程和具体类型。这减少了代码的耦合度,使系统更易于维护和扩展。
- 产品族的一致性:使用一个具体工厂创建的产品对象可以确保属于同一个产品族,且它们之间是兼容的。这避免了客户端在组合不同产品时可能出现的不兼容问题。
- 易于扩展:当需要引入新的产品族时,只需添加新的具体工厂类和对应的具体产品类,而不需要修改现有代码。这样能够确保系统的开放-封闭原则,即对扩展开放,对修改封闭。
缺点:
- 难以支持新产品类型:如果要添加新的产品等级结构,需要修改抽象工厂类及所有的具体工厂类,这违反了开放-封闭原则,增加维护成本。因此在使用抽象方法模式之前要进行全面考虑,尽量不要在设计完成后增加或删除产品等级结构。
代码示例
from abc import ABC, abstractmethod# 抽象产品 - 按钮
class Button(ABC):@abstractmethoddef click(self):pass# 抽象产品 - 文本框
class TextBox(ABC):@abstractmethoddef input(self, text):pass# 具体产品 - Windows 按钮
class WindowsButton(Button):def click(self):print("Windows Button Clicked")# 具体产品 - Windows 文本框
class WindowsTextBox(TextBox):def input(self, text):print(f"Windows TextBox input: {text}")# 具体产品 - Mac 按钮
class MacButton(Button):def click(self):print("Mac Button Clicked")# 具体产品 - Mac 文本框
class MacTextBox(TextBox):def input(self, text):print(f"Mac TextBox input: {text}")# 抽象工厂
class GUIFactory(ABC):@abstractmethoddef create_button(self):pass@abstractmethoddef create_textbox(self):pass# 具体工厂 - Windows 工厂
class WindowsFactory(GUIFactory):def create_button(self):return WindowsButton()def create_textbox(self):return WindowsTextBox()# 具体工厂 - Mac 工厂
class MacFactory(GUIFactory):def create_button(self):return MacButton()def create_textbox(self):return MacTextBox()# 客户端代码
def client(factory: GUIFactory):button = factory.create_button()textbox = factory.create_textbox()button.click()textbox.input("Hello World")# 使用 Windows 工厂
print("Using Windows Factory:")
client(WindowsFactory())# 使用 Mac 工厂
print("\nUsing Mac Factory:")
client(MacFactory())
抽象工厂模式和工厂方法模式的比较
抽象工厂模式是工厂方法模式的进一步延伸,我们从以下几点进行比较它们:
- 系统开销:工厂方法模式中的每个工厂只生产一种产品,可能会导致系统中存在大量的工厂类,会增加系统的开销。而抽象工厂模式将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产,极大地减少了工厂类的数量。
- 扩展性:工厂方法模式增加新产品比较容易,只需要增加对应产品类和工厂方法类即可。抽象工厂模式增加新的产品族比较容易,但增加新的产品类型,需要修改抽象工厂类及所有的具体工厂类,扩展性稍差。
- 适用场景:工厂方法模式适用于系统只需要一个产品的多种变体的场景,抽象方法模式适用于系统需要创建多个相关产品族的场景。
参考
《设计模式的艺术》
相关文章:
Python设计模式 - 抽象工厂模式
定义 抽象工厂模式是一种创建型设计模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 产品等级结构与产品族 为了更好地理解抽象工厂模式,先引入两个概念: 产品等级结构:就是产品的…...
【JavaEE初阶】懒汉模式与饿汉模式及指令重排序问题
目录 📕 单例模式 🌳 饿汉模式 🚩 线程安全 🎍 懒汉模式 🚩 懒汉模式-单线程版 🚩 懒汉模式-多线程版 🎄 指令重排序 📕 单例模式 单例模式是一种经典的设计模式,…...
Vue3使用Cascader 级联选择器如何获取值并提交信息
我写了一个用户对象,有address地址字段,我怎么将用户选择的级联数据selectedValue值传给address,并将对象返回给后端,核心代码实现了该问题。 <script> 核心代码: //获取住址并更新给addresslet selectedValue…...
Python面试整理-第三方库
Python社区提供了大量的第三方库,这些库扩展了Python的功能,覆盖了从数据科学到网络应用开发等多个领域。以下是一些非常流行和广泛使用的第三方库: 1. NumPy ● 用途:数值计算。 ● 特点:提供了一个强大的N维数组对象和大量用于数学运算的函数。 ● 应用场景:科学计算、…...
电脑添加虚拟网卡与ensp互联,互访
一、按照过程 1、打开设备管理器 2、点击网络适配器,点击左上角操作,点击“添加过时硬件” 3、下一页 4、选择“安装我手动从列表选择的硬件”,下一页 5、下拉,选择“网络适配器”,下一页 6、厂商选择“Microsoft”&…...
悬而未决:奇怪的不允许跨域CORS policy的问题
我在本地HBuilderX中进行预览写好的前端网页,它里面用了ajax访问了远程服务器的后端API网址,不出意外地报不允许跨域访问的错了:Access to XMLHttpRequest at ‘http://xxx.com/MemberUser/login’ from origin ‘http://mh.com’ has been b…...
索引优化秘籍:SQL Server数据库填充因子的调优艺术
索引优化秘籍:SQL Server数据库填充因子的调优艺术 在SQL Server的性能优化中,索引起着至关重要的作用。而索引填充因子(Fill Factor)则是控制索引页填充程度的重要参数,它直接影响索引的存储效率和查询性能。本文将深…...
ffmpeg 的内存分配架构
------------------------------------------------------------ author: hjjdebug date: 2024年 08月 01日 星期四 18:00:47 CST descripton: ffmpeg 的内存分配架构1 ------------------------------------------------------------ ffmpeg 的内配分配搞的人晕菜&#…...
Vue+live2d实现虚拟人物互动(一次体验叙述)
目录 故事的开头: 最终的实现效果: 实现步骤: 第一步:下载重要文件 第二步:创建vue项目文件,将刚下载文件拷贝到public目录下 第三步:在index.html文件中引入js 第四步:使用&…...
内联函数的概念和用途以及区别
内联函数(Inline Function)是C(以及C99之后的C语言)中的一个特性,旨在通过减少函数调用的开销来提高程序的执行效率。在正常情况下,当程序调用一个函数时,会发生一系列的操作,包括保…...
rust 桌面 sip 软电话(基于tauri 、pjsip库)
本文尝试下rust 的tauri 桌面运用 原因在于体积小 1、pjsip 提供了rust 接口官方的 rust demo 没编译出来 在git找了个sip-phone-rs-master https://github.com/Charles-Schleich/sip-phone-rs 可以自己编译下pjsip lib库替换该项目的lib 2、创建一个tauri demo 引用 [depe…...
Linux 进程优先级、程序地址空间、进程控制
个人主页:仍有未知等待探索-CSDN博客 专题分栏: Linux 目录 一、进程优先级 1、什么是进程优先级? 2、为什么要有优先级? 3、Linux的优先级特点、查看方式 4、命令行参数和环境变量 1.命令行参数 2.环境变量 获取环境变量的…...
学习笔记一
vector 在创建时指定初始大小和初始值: vector<int> a(5, 1) // 包含 5 个整数的 vector,每个值都为 1 可以使用 push_back 方法向 vector 中添加元素: a.push_back(7) // 将整数 7 添加到 vector 的末尾 可以使用 size(…...
Linux中信号的发送及信号的自定义捕捉方法
预备知识: 信号产生时进程早已知道该信号如何处理。 信号产生时进程可能并不能立即处理信号而是等到合适的时候处理。 信号其他相关常见概念 实际执行信号的处理动作称为信号递达(Delivery) 信号从产生到递达之间的状态,称为信号未决(Pending)。 进程可以选择阻…...
yum仓库的制作与使用
目录 前言: 1 查看系统内核 2 获取网络源 3 搭建yum网络仓库 4 rpm包的下载 4.1 将rpm包下载至本地 4.2 对下载的rpm包进行备份 5 制作本地yum源 5.1 软件仓库制作工具createrepo 5.2 使用createrepo创建本地yum仓库 6 搭建docker本地仓库 前言&#x…...
牛客周赛54:D.清楚姐姐跳格子(bfs)
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 \,\,\,\,\,\,\,\,\,\,老妪遂递一羊皮卷轴,上面什么都没有,清楚欲问,老妪却缄口不言。 \,\,\,\,\,\,\,\,\,\,清楚性格刚直&…...
用户空间 lmkd
用户空间 lmkd 1、概览1.1 配置lmkd 2、lmkd2.1 lmkd启动2.2 时序图 Android LowMemoryKiller原理分析 AOSP>文档>核心主题低内>存终止守护程序 1、概览 Android Low Memory Killer Daemon :system/memory/lmkd/README.md Android 低内存终止守护程序 (lm…...
二叉树专题
Leetcode 104. 二叉树的最大深度 class Solution { public:int maxDepth(TreeNode* root) {if(!root) return 0;int leftd maxDepth(root -> left) 1;int rightd maxDepth(root -> right) 1;return max(leftd, rightd);} }; Leetcode 100. 相同的树 class Solution…...
Spring MVC 之简介及常见注解
一、什么是 Spring MVC Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从一开始就包含在 Spring 框架中。它的正式名称 “Spring Web MVC” 来自其源模块的名称 (Spring-webmvc),但它通常被称为"Spring MVC"。 什么是Servlet呢? S…...
除了使用本地存储,还有哪些方法可以实现只出现一次的弹窗?
除了使用本地存储,还有以下几种方法可以实现只出现一次的弹窗: 1.使用 Cookie:可以将一个标识符存储在浏览器 Cookie 中,下次用户访问页面时检查 Cookie 中是否存在该标识符,从而判断是否需要显示弹窗。 2.使用服务器端…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
