Python设计模式 - 工厂方法模式
定义
工厂方法模式是一种创建型设计模式,它定义一个创建对象的接口,让其子类来处理对象的创建,而不是直接实例化对象。
结构

抽象工厂(Factory):声明工厂方法,返回一个产品对象。具体工厂类都必须实现该方法。
具体工厂(Concrete Factory):实现工厂方法以创建具体的产品对象。
抽象产品(Product):定义产品对象的接口。
具体产品(Concrete Product):实现产品接口的具体产品对象。
应用场景
- 产品类型繁多且结构相似:当产品类型较多且具有相似的结构时,可以使用工厂方法模式来管理创建逻辑。抽象工厂类定义抽象方法,具体工厂类实现抽象方法创建具体的产品对象,从而简化客户端代码。例如不同类型的日志记录器、不同类型的报表生成器等。
- 处理复杂创建过程:当对象的创建过程比较复杂,需要很多步骤或依赖其他对象。工厂方法模式可以将这些复杂的创建过程封装在工厂方法中,从而简化客户端代码,并确保对象创建的一致性。例如,不同类型的数据库连接、复杂的对象初始化流程等。
- 系统需要良好的扩展性:当系统需要能够方便地引入新的产品对象时,可以使用工厂方法模式。通过新增具体工厂类并实现工厂方法,可以在不修改现有代码的情况下扩展系统的功能。
优缺点
优点:
- 简化客户端代码:客户端代码不需要了解具体产品类的创建细节,只需调用工厂类的创建方法即可获得所需的对象。这减少了客户端代码的复杂性,使其更容易维护和理解。
- 提高代码的可维护性:工厂方法模式将复杂的对象创建过程封装在工厂方法中,客户端代码不需要关心对象的创建细节,从而简化了代码的维护。
- 符合开闭原则:工厂方法模式符合面向对象设计中的开闭原则,即对扩展开放,对修改关闭。新增产品类时,无需修改现有的工厂类,只要新增具体工厂类即可。
缺点:
- 增加代码复杂性:工厂方法模式引入了额外的类和接口,这可能会增加代码的复杂性,也会增加运行时资源的开销,尤其是在产品类和工厂类数量较多的情况下。
代码示例
from abc import ABC, abstractmethod# 抽象产品类
class Vehicle(ABC):@abstractmethoddef drive(self) -> str:pass# 具体产品类 - 汽车
class Car(Vehicle):def drive(self) -> str:return "Driving a car"# 具体产品类 - 自行车
class Bicycle(Vehicle):def drive(self) -> str:return "Riding a bicycle"# 抽象工厂类
class VehicleFactory(ABC):@abstractmethoddef create_vehicle(self) -> Vehicle:pass# 具体工厂类 - 汽车工厂
class CarFactory(VehicleFactory):def create_vehicle(self) -> Vehicle:return Car()# 具体工厂类 - 自行车工厂
class BicycleFactory(VehicleFactory):def create_vehicle(self) -> Vehicle:return Bicycle()# 客户端代码
def client_code(factory: VehicleFactory) -> None:vehicle = factory.create_vehicle()print(f"Client: {vehicle.drive()}")if __name__ == "__main__":print("App: Using the CarFactory.")client_code(CarFactory())print("\n")print("App: Using the BicycleFactory.")client_code(BicycleFactory())
工厂方法模式和简单工厂模式的比较
工厂方法模式是简单工厂模式的延伸,它继承了简单工厂模式的优点,同时也弥补了简单工厂模式的不足。它针对不同的产品提供不同的工厂,可以很好地解决简单工厂模式的以下两个问题:
- 违反开闭原则:每当需要添加新的产品类型时,都必须修改工厂类以添加新的创建逻辑,违反了开闭原则。
- 可能包含大量的条件判断:工厂类中的条件判断语句会随着产品种类的增加而变得冗长且复杂。
工厂方法模式和简单工厂模式适用于不同的场景:
- 简单工厂模式的灵活性和扩展性较低,适用于产品种类相对固定且变化不频繁的场景。工厂方法模式适用于产品种类较多且经常变化的场景,尤其需要在不修改现有代码的情况下添加新产品时。
- 简单工厂模式的实现和使用都较简单,适合小型系统或简单场景。工厂方法模式的实现和使用都较复杂,适合大型系统或复杂场景。
参考
《设计模式的艺术》
相关文章:
Python设计模式 - 工厂方法模式
定义 工厂方法模式是一种创建型设计模式,它定义一个创建对象的接口,让其子类来处理对象的创建,而不是直接实例化对象。 结构 抽象工厂(Factory):声明工厂方法,返回一个产品对象。具体工厂类都…...
学习记录:ESP32控制舵机 FREERTOS BLE
控制舵机 PWM信号 PWM信号是一种周期性变化的方波信号,它有两个关键参数: 周期(Period):一个完整的PWM信号的时间长度,通常用秒(s)或毫秒(ms)表示。占空比…...
react中的useState和Hook、副作用
react的组件分为类组件和函数组件,Hook 是一种特殊的函数,可以让你在函数组件中使用类组件中才有的一些特性。useState、useEffect、useReducer都是Hook。其中useState用于在函数组件中添加状态,useEffect用于在函数组件中执行副作用…...
Linux嵌入式学习——数据结构——线性表的链式结构
线性表的链式存储 解决顺序存储的缺点,插入和删除,动态存储问题。 特点: 线性表链式存储结构的特点是一组任意的存储单位存储线性表的数据元素,存储单元可以是连续的,也可以不连续。可以被存储在任意内存未被占…...
文本编辑 文本中的各种空格
参考资料 欧文の半角スペースは2種類ある!?无中断空格常见空格一览浅析什么是零宽度字符以及零宽度字符在实际中的应用场景空格象形字间隔无中断空格零宽间隔 目录 零. 各种空格在Notepad中的效果一. 半角空格二. 全角空格三. TAB空格四. 无中断空格4.1 定义4.2 H…...
Vue插槽 (Slots)详解
目录 前言基础插槽具名插槽作用域插槽默认插槽动态插槽名总结相关阅读 前言 Vue的插槽(Slots)是一个非常强大的特性,它允许你在组件的模板中嵌入父组件的内容。插槽使得组件之间的内容分发变得灵活,尤其在构建可复用组件时非常…...
Unity中有关Animation的一点笔记
也许更好的阅读体验 Animation Unity中Animation类并不是直接记载了和播放动画有关的信息,可以简单理解Animation为一个动画播放器,播放的具体内容就像卡带一样,当我们有了卡带后我们可以播放动画。 对应的则是编辑器中的组件 所以Anima…...
module federation模块联邦与微前端
module federation是什么 webpack5新增了module federation,module federation的作用,将每个构建(build)作为容器(这是一个概念),构建后的资源可以正常部署,同时还具备在运行时对外暴露其中的模块,这就意味着多个构建…...
日常开发记录分享——C#控件ToolTip实现分栏显示内容
文章目录 需求来源实现思路实施请看VCR等等别走,有优化 需求来源 需要在鼠标浮动到指定位置后提示出详细的信息,一开始使用的tooltip实现,但是里面的内容效果并不理想,需要有条理性,于是就想到能不能将展示的东西分列…...
Kettle下载安装
环境说明 虚拟机:Win7;MySql8.0 主机:Win11;JDK1.8;Kettle 9.4(Pentaho Data Integration 9.4)(下载方式见文末) 安装说明 【1】解压后运行Spoon.bat 【2】将jar包 复…...
最新版Golang pprof使用(引入、抓取、分析,图文结合)
最新版Golang pprof使用 🔥具体实践: Go调试神器pprof使用教程Golang线上内存爆掉问题排查(pprof) Github地址:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-pprof 引入pprof:import _ “net/http/pprof” …...
vue3学习记录1:emit的写法
emit是用于child组件向parent组件通信的工具,因为vue3的script可以设置为setup,写法同vue2有较大区别。 一、script setup - 直接写 <script lang"ts" setup>const emit defineEmits([close]);function handleClose() {emit(close);}…...
Visual Studio Code + vue快速安装配置Node.js+Vue+webpack+vscode
第一部分:Node.js 第一步:下载Node.js 方法1:链接 下载 | Node.js 中文网 (nodejs.cn) 方法2:百度网盘 链接:https://pan.baidu.com/s/1zIqu8H9rb_I1i-1OWD7swQ?pwdaurk 提取码:aurk --来自百度网盘…...
【Dart 教程系列第 49 篇】什么是策略设计模式?如何在 Dart 中使用策略设计模式
这是【Dart 教程系列第 49 篇】,如果觉得有用的话,欢迎关注专栏。 博文当前所用 Flutter SDK:3.22.1、Dart SDK:3.4.1 文章目录 一:什么是策略设计模式?二:为什么要使用策略设计模式࿱…...
BGP路由反射器
原理概述 缺省情况下,路由器从它的一个 IBGP对等体那里接收到的路由条目不会被该路由器再传递给其他IBGP对等体,这个原则称为BGP水平分割原则,该原则的根本作用是防止 AS内部的BGP路由环路。因此,在AS内部,一般需要每台…...
DolphinDB Web 端权限管理:可视化操作指南
在现代数据库管理中,高效和直观的权限管理对于用户的数据安全是至关重要的。过去 DolphinDB 用户需要依赖系统脚本来管理用户和权限,这对于缺乏技术背景的管理员来说既复杂又容易出错。 为了提升用户体验和操作效率,DolphinDB 目前在 Web 上…...
学习Vue2收藏这一篇就够了(如何创建Vue实例)
什么是Vue? Vue是什么:是一个用于构建用户界面的渐进式框架 什么是构建用户界面:基于数据动态渲染页面 什么是渐进式:循序渐进的学习 什么是框架:一整套完整的项目解决方案 创建Vue实例 核心步骤(4步…...
Mysql数据库第四次作业
mysql> create table student(sno int primary key auto_increment,sname varchar(30) not null unique,Ssex varchar(2) check (Ssex男 or Ssex女) not null,Sage int not null,Sdept varchar(10) default计算机 not null); mysql> create table Course(Con int primar…...
使用Docker搭建MySql的主从同步+ShardingSphere搭建Mysql的读写分离
参考课程 尚硅谷ShardingSphere5实战教程(快速入门掌握核心)_哔哩哔哩_bilibili 主服务器 创建容器 docker run -d \ -p 3306:3306 \ -v /kira/mysql/master/conf:/etc/mysql/conf.d \ -v /kira/mysql/master/data:/var/lib/mysql \ -e MYSQL_ROOT…...
数据结构:数据类型与抽象数据类型
数据类型与抽象数据类型 数据类型基本数据类型构造数据类型指针类型枚举类型 抽象数据类型(ADT)抽象数据类型的组成部分常见的抽象数据类型示例 数据类型与抽象数据类型的区别实现抽象数据类型的具体方式用数组实现栈用链表实现栈 总结 数据类型 数据类…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
