工厂方法模式(Factory Method) - 指南
在本章节中,我们将开始讨论五种创建型设计模式中的工厂方法模式(Factory Method)。
理论部分
定义
工厂方法模式是一种创建型设计模式,它提供了一种将对象实例化过程封装起来的方法,让子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类中进行。
概括来说就是:在父类中提供一个创建对象的接口来让子类决定具体实例化什么类型的对象。
在游戏中,我们需要设计多种武器种类,每个武器和道具都有不同的属性功能以及品质等等私有字段,这种情况下,我们便可以借助武器装备道具工厂对象根据游戏状态或者玩家操作动态地创建具体的装备对象。
- 例如:我们定义了一个武器基类
Weapon
,其中有一个纯虚方法use
代表使用这把武器的逻辑。
//武器基类
class Weapon
{
public:
virtual void use() = 0;
};
那么我们便可以派生出剑和弓的子类,它们分别有自己的使用逻辑。
// 武器 - 剑
class Sword
: public Weapon
{
public:
void use() override
{
std::cout <<
"挥舞剑!" << std::endl;
}
};
// 武器 - 弓
class Bow
: public Weapon
{
public:
void use() override
{
std::cout <<
"射出箭!" << std::endl;
}
};
通常来说,如果我们不考虑使用任何设计模式,这两个子类就是可以直接被实例化和使用的。
如果我们要使用工厂方法模式进行优化,就需要创建工厂基类,
// 武器的工厂模式基类
class WeaponFactory
{
public:
virtual Weapon* createWeapon() = 0;
// 纯虚函数
};
工厂类约定所有生成具体武器的工厂都需要实现createWeapon
方法,对外返回创建后的对象。
所以我们就需要实现具体的工厂子类了,对应了我们生成武器剑的工厂和生成武器弓的工厂。
// 武器剑的工厂
class SwordFactory
: public WeaponFactory
{
public:
Weapon* createWeapon() override
{
return new Sword();
}
};
// 武器弓的工厂
class BowFactory
: public WeaponFactory
{
public:
Weapon* createWeapon() override
{
return new Bow();
}
};
这样,我们便可以通过具体的工厂对象创建对应的武器产品了。
- 由此我们可以得出工厂模式的几个关键要素:
- 抽象产品(Product):定义了产品的接口
如Weapon
基类(重要声明,意味着后续所有创建者及其子类构建的对象都将是通用的)
- 具体产品(ConcreteProduct):实现抽象产品接口的具体类
如Sword
和Bow
子类(抽象产品接口的不同实现)
- 抽象创建者(Creator):声明工厂方法,返回产品对象
如WeaponFactory
基类(不直接进行具体的产品创建,而是负责对创建的接口进行声明,后续所有的创建者返回的对象类型都必须与产品类型相匹配)
- 具体创建者(ConcreteCreator):重写工厂方法,返回具体产品实例
如SwordFactory
和BowFactory
子类(重写抽象工厂的方法,实例化不同的产品对象进行返回)
所以我们可以得出工厂方法的显著优点:
- 解耦将客户端代码与具体类依赖
将具体的产品代码与使用该产品的客户端内容进行分离
- 符合开闭原则,提高系统的可扩展性
引入新产品无需修改现有代码
- 符合单一职责原则,封装复杂的对象创建逻辑
工厂内部屏蔽对象创建和初始化的复杂操作
- 提高可维护性
将对象创建代码的逻辑集中到一处方便后续修改维护
- 支持更多的产品组合
抽象工厂模式的基础思想
应用场景
- 日志系统
提供输出到控制台、文件、网络和数据库的多种方法
- 数据库驱动
提供连接到MySql、SQLite、PostgreSQL等不同数据库的驱动层
- 文档生成
将同一份内容生成HTML、PDF、Markdown等不同格式的文档。
缺点
引入许多新的子类,可能增加代码复杂度
单独的工厂方法模式无法应对复杂的产品族和变种
这篇博文是我的学习笔记
相关文章:
工厂方法模式(Factory Method) - 指南
工厂方法模式(Factory Method) - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !importa…...
拾忆录
████,也即言多██,就是少点██,不容易发生██——来自于多种████的通理 择一███,遇一人██——收集自███,████ 知行合一心学理论——王阳明...
从零搭建RAG应用:跳过LangChain,掌握文本分块、向量检索、指代消解等核心技术实现
RAG(检索增强生成)本质上就是给AI模型外挂一个知识库。平常用ChatGPT只能基于训练数据回答问题,但RAG可以让它查阅你的专有文档——不管是内部报告、技术文档还是业务资料,都能成为AI的参考资源。 很多人第一反应是用LangChain或LlamaIndex这些现成框架,确实能快速搭起来。…...
python高阶技巧
闭包:在函数嵌套前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数叫做闭包 简单闭包: def outer(logo): def inner(msg): print(f"<{logo}>{msg}>{logo}") return inner fn1=outer("黑马程…...
机器视觉之图像处理篇 - 指南
机器视觉之图像处理篇 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-s…...
尝试hikari和jdbctemplate
试着基于jdbctemplate包装一个MysqlHelper类。连接池采用springboot默认的hikari。jdbctemplate提供基本的防注入,它的写法比jdbc好看,jdbc还需要putint,putstr。提供的另一个功能是结果集的转换。写完,测试代码的面貌如下:var sqlhp = new SqlHelper();sqlhp.configAddress…...
配置Nginx根据IP地址进行流量限制以及返回JSON格式数据
要在Nginx中根据IP地址进行流量限制并返回JSON格式数据,你需要结合Nginx的 ngx_http_limit_req_module模块和一些配置技巧。这个模块允许你基于定义的键值,比如IP地址,限制请求的速率。不过在进入细节前,别忘了备份你的Nginx配置文件 划重点:配置透视战斗护甲 (limit_req_…...
回归
最近因为████导致██发生████,长期的██也不是办法,我决定以███████发文。 我的很多比如███,███都发生了██,所以██的██████视█。 重新██...
CSS纯文本渐变动效
创建一个令人印象深刻的CSS文本渐变动效就像是在文字上施展魔法。想象你的文字就像是一幅幻灯片,色彩在背后流转,让每个字母都像是被彩虹绘制过一样。 为了让这种魔法发生,你需要进入CSS的巫术领地。我们将把渐变动效的制作分解为简单步骤,这样即使你不是CSS的大师,也能轻…...
泛微流程共享
第一步: 第二步:打开合同审批数据,点击右键,选择共享。 第三步:共享权限的查看,可见Giada没有查看权限。 第四步:添加权限,依次进入下面的选项。...
MySQL报错:未知系统变量tx_isolation及隔离级别查询
MySQL在其各个版本中进行了诸多变更和优化,包括系统变量、参数命名、功能等方面的调整。在这个情况中,遇到“未知系统变量tx_isolation”这个错误是因为在MySQL 8.0及以后的版本中,系统变量 tx_isolation已经被重命名为 transaction_isolation。 如果你像老朋友一样寻找 tx_…...
Redssion
1.使用 // 设置锁定资源名称 RLock disLock = redissonClient.getLock("DISLOCK"); //尝试获取分布式锁 boolean isLock= disLock.tryLock(500, 15000, TimeUnit.MILLISECONDS); if (isLock) {try {//TODO if get lock success, do something;Thread.sleep(15000);} …...
if __name__ == __main__:
if __name__ == "__main__": 是 Python 中的一个标准代码块,用于检查一个脚本是否是直接运行的。 工作原理 当一个 Python 脚本被解释器执行时,它会自动定义一些特殊变量。其中一个就是 __name__。如果脚本是直接运行的,Python 会将 __name__ 变量的值设置为 &quo…...
提升系统可靠性:Air8000多串口硬件设计的黄金法则
串口通信的可靠性直接影响工业系统的连续性。Air8000以多串口工业级连接力赋能设备互联,而硬件设计则是其可靠性的根基。总结黄金法则,从信号隔离、阻抗匹配到热设计,全方位保障串口通信的稳定性与安全性。 本文主要从硬件设计的角度,分享串口设计中的一些关键注意点,软件…...
20250915笔记
svn 版本控制工具 一、svn介绍 二、svn安装 1、下载客户端和服务端 安装流程: (1)先安装服务端 (2)在服务端创建仓库 (3)新建用户,新建用户组 (4)设置权限,服务端安装成功 (5)安装客户端(也叫小乌龟) (6)安装桌面右键连接仓库 (7)输入账号和密码 (8)连接…...
enumerate函数
enumerate() 是 Python 中一个非常实用的内置函数,它用于在遍历一个可迭代对象(如列表、元组、字符串等)的同时,获取每个元素的索引和值。 为什么需要 enumerate()? 在没有 enumerate() 之前,如果你想同时获取索引和值,通常需要手动维护一个计数器: fruits = [apple, b…...
2025国内 HR SaaS 竞争格局:易路以AI深度融合引领行业转型
在中国企业数智化转型的浪潮中,HR SaaS 市场正经历从基础数字化向智能协同的关键跃迁。随着全球化布局与本地化合规要求的双重驱动,中大型企业对人力资源管理系统的需求已从单一模块效率提升转向全流程智能协同与全球合规管理。截至 2025 年,中国 HR SaaS 市场规模已突破 30…...
HyperWorks许可激活
在工程项目中,高效的软件工具是成功的关键。而一个顺畅的许可激活流程,则是确保这些工具能够迅速投入使用的重要环节。HyperWorks,作为一款领先的工程仿真软件,以其快速、简便的许可激活流程,为用户提供了卓越的使用体验。 一、一键激活,轻松上手 HyperWorks的许可激活流…...
f-string用法
在 Python 3.6 及更高版本中,在字符串前加上一个 f,表示这是一个 f-string(格式化字符串字面量)。 f-string 的主要作用是让你在字符串中嵌入 Python 表达式,使得格式化字符串变得非常简洁和直观。 f-string 的基本用法 你只需要在字符串开头加上 f,然后在字符串内部用花…...
OpenStack Nova instance 常见操作
1. 启动实例(start) 场景:启动处于 SHUTOFF 状态的实例 源码路径:API 层:nova/compute/api.py → start() RPC 层:nova/compute/rpcapi.py → start_instance() 执行层:nova/compute/manager.py → start_instance() 驱动层:nova/virt/libvirt/driver.py → power_on()…...
libdpi.dll libdatareport.dll libdash_plugin.dll libcurl-x86.dll libcurl-x64.dll libcurl_x64.dll - 指南
libdpi.dll libdatareport.dll libdash_plugin.dll libcurl-x86.dll libcurl-x64.dll libcurl_x64.dll - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas"…...
理解 Kubernetes CSI
关于 Kubernetes CSI,现在的资料已经不少,但我仍希望有一篇文档能让人轻松但不失准确地理解 CSI。 本文不涉及代码分析和详细设计。但需要如下基础:会使用至少一种容器,Docker,containerd,Kata 之类的都可以。 protobuf 和 gRPC:会用并有少量的开发经验,会用某种语言(…...
9.15
开学...
常用数学定理公式
二项式定理 \[(x + y)^n = \sum_{k=0}^n \binom{n}{k} x^{n-k} y^k \]...
线性规划
线性规划是求一个线性函数在满足一组线性等式或不等式方程条件下极值的一类数学问题的统称。要求目标函数和约束方程必须是线性函数。隐含了如下假定: 比例性假定:决策变量的变化与资源消耗成比例; 可加性假定:每个决策变量的影响独立于其他变量; 连续性假定:决…...
伪代码学习总结
伪代码学习总结 1. 什么是伪代码伪代码(Pseudocode) 是一种 算法描述语言。它既不同于自然语言(太模糊),也不是某种具体编程语言(太依赖语法)。使用伪代码的目的:使被描述的算法可以容易地翻译成任何一种编程语言(如 Pascal, C, Java, Python 等); 要求 结构清晰、可…...
20号胶 2511
...
9.13linux系统命令
Linux2系统命令 1、df 查看磁盘使用情况 (1)df 查看磁盘使用情况 Filesystem:代表该文件系统时哪个分区,所以列出的是设备名称。 1K-blocks:说明下面的数字单位是1KB,可利用-h或-m来改变单位大小,也可以用-B来设置。 Used:已经使用的空间大小。Available:剩余的空间…...
9.15 svn git
svn版本控制工具 一、svn介绍 SVN是subversion的简称 是一个开放源代码的版本控制系统,通过采用分支管理系统的高 效管理,简而言之就是用于多个人共同开发同一个项目,实现共 享资源,实现最终集中式的管理。 SVN的作用:在项目组当中对需求规格说明书、测试用例、产品 说明书…...
PVC2601
...
利用RabbitMQ与Redis实现消息的延迟传递的策略
RabbitMQ:时间控的快递中心 让我们从RabbitMQ开始,RabbitMQ拥有一个叫做“Dead Letter Exchanges”(DLX)的机制,这个机制基本上就是一个失物招领处。当一个消息未能及时被送达,RabbitMQ会将它转移至DLX。这个DLX与一个或多个队列关联,这样就能处理这些失去方向的消息了。…...
python 按excel的经纬度提取对应栅格tif文件的数值
栅格文件 批量处理代码:# -*- coding:utf-8 -*- """ @author: suyue @file: extract_stations_from_excel.py @time: 2025/09/09 @desc: 从Excel读取站点信息并提取所有站点的CTT值 """ import rasterio import numpy as np import pandas as p…...
麒麟
麒麟点击跳转...
实现我的第一个本地文档问答机器人
本地文档问答机器人 下面是一个完整的本地文档问答机器人实现,涵盖了阶段三的所有核心概念:文档加载、文本分割、向量存储和检索增强生成(RAG)。 完整代码实现 import os.path from typing import Listfrom huggingface_hub import snapshot_download from langchain.chain…...
17、逻辑回归与分类评估 - 从连续到离散的智能判断 - 教程
17、逻辑回归与分类评估 - 从连续到离散的智能判断 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", m…...
关于32位单片机使用lwip无法访问(ping)外网,只能与同网段设备进行通信的问题解决
核心问题:MAC地址 理论依据:MAC地址是有相应的规范的MAC地址中,前3字节为组织唯一标识符,后24位由厂家自行定义。也就是说前3字节是有规定的,其中前3字节MAC中的前几位也是有着对应的含义的。MAC地址详细的介绍,大家可以在网上搜得到 出现这个问题的核心就是网关对设备mac地…...
044-WEB攻防-PHP应用SQL盲注布尔回显延时判断报错处理增删改查方式
044-WEB攻防-PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式 1.演示案例:➢PHP-MYSQL-SQL操作-增删改查 ➢PHP-MYSQL-注入函数-布尔&报错&延迟 ➢PHP-MYSQL-注入条件-数据回显&错误处理 ➢PHP-MYSQL-CMS案例-插入报错&删除延迟…...
多品牌摄像机视频平台EasyCVR海康大华宇视视频平台统一接入方案
多品牌摄像机视频平台EasyCVR海康大华宇视视频平台统一接入方案在实际的工程项目里,我们常常会面临这样的情况:项目管理者可能会决定使用多个品牌的视频监控摄像头,或者有需求将现有的、多种类型的监控系统进行整合。现在,让我们来探讨一下如何实现不同品牌摄像头的连接和使…...
离散数学课堂习题及课后习题 - PPX
课上的习题,不完整,有空再更新第二章 抽屉原理 Background: 简单形式: 把(n+1)个物体放入n个盒子,必有一个盒子中装了两个物体。其实这个也是狄利克雷描述的一个特殊的表述(如果对于一个映射$ X\to Y $ ,如果\(|X|>|Y|\),则\(f\)不可能是单射,也就是会有\(f(x_1)=f(x…...
玻璃2601
前期五浪下跌走完了 开启反弹...
GoFrame框架查询数据表时对字段取别名
两种方式,基于模型的Fields方法dao.User.Where("id",1).Fields("name as `nickname`","id as `uid`").All()基于结构体orm标签的映射关系type UserData struct {Uid int `json:"id" orm:"id"`Nickname string `json:"…...
ubuntu安装mysql矩阵
安装mysql 5.7版本ubuntu版本 mysql版本 xtrabackup版本 ldd显示GLIBC版本 依赖库处理方式18.04 5.7.42 2.4.28 2.27 不需要处理20.04 5.7.42 2.4.28 …...
二十、DevOps落地:Jenkins基础入门(一)
二十、DevOps落地:Jenkins基础入门(一) 目录二十、DevOps落地:Jenkins基础入门(一)1、DevOps初识1.1 什么是DevOps1.2 DevOps相关工具链1.3 什么是CICD?1.4 持续集成CI介绍1.5 持续交付和持续部署CD介绍1.6 什么是Pipeline(流水线)?1.7 Pipeline编排任务的优势1.8 Pi…...
ubuntu 22.04安装mysql5.7
环境Os:ubuntu 22.04 desktop桌面版mysql:mysql-5.7.42-linux-glibc2.12查看操作系统信息root@db:~# ldd --version ldd (Ubuntu GLIBC 2.35-0ubuntu3) 2.35 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions…...
Docker如何获取镜像
可以使用 docker pull 命令来从仓库获取所需要的镜像。...
2025 ICPC 网络赛2 E
E. Zero 矩阵快速幂优化 dp。 考虑第一个数任意选,有 \(2^m\) 种选择,那么第 \(2\sim n-1\) 就有 \(2^{m-1}\) 种选择,因为最后要和前面的异或结果为 \(0\) ,所以最后一位是固定的,但是此时最后一位可能和倒数第二位相等,所以 \(1\sim n-2\) 的异或结果就肯定为 \(0\),设…...
偏移寻址
相对寻址. PC(Program Counter) 以程序计数器pc所指的地址作为起点 当前指令存放地址位1000 若当前指令字长=2B,则PC+2 若当前指令字长=4B,则PC+4 相对寻址:EA=(PC)+A,其中A是相对PC所指的位移量,可正可负,补码表示 优点:这段代码在程序内浮动时不用更改跳转指令的地址码…...
Stringbuilder操作和stringjoiner
使用stringbuilder容器可以方便对字符串的,是java自带的类 两个方法操作完成后默认返回值都是stringbuilder或者stringjoiner类型不是string,需要转换 Stringjoiner: length返回的是所有字符的总个数,包括空格和符号...
西电微机原理与接口技术笔记总结
笔记链接西电微机原理-第一章 序论:微型计算机概述 西电微机原理-第二章Intel单核处理器 西电微机原理-第三章 Intel处理器指令系统及汇编语言(1) 西电微机原理-第三章 Intel处理器指令系统及汇编语言(2) 西电微机原理-第三章 Intel处理器指令系统及汇编语言(3) 西电微机…...
abc423 F - Loud Cicada
F - Loud Cicada 题意 给你 \(n\) 个数 \(a_i\),问有多少个 \(x \in [1,Y]\) 满足 \(a_i \mid x\) 的 \(i\) 的个数等于 \(m\)。 \(n ,m \le 20, a_i,Y \le 10^{18}\)。 思路 \(a_i \mid x\) 的 \(x\) 有 \(\lfloor \frac{Y}{a_i} \rfloor\) 个。 显然可以枚举 \(i\) 的集合,…...