漫谈设计模式 [2]:工厂方法模式

news2024/9/17 4:06:50

引导性开场

菜鸟:老鸟,我在项目中遇到一个问题。每当需要创建对象时,我都直接使用类的构造函数,但随着项目复杂度的增加,这种方法变得越来越不可维护。你有什么建议吗?

老鸟:你提到的问题很常见。直接使用构造函数在简单场景下还行,但在复杂项目中会导致代码耦合度高、维护困难。你听说过工厂方法模式吗?

菜鸟:工厂方法模式?好像听过,但不太了解具体是什么。

渐进式介绍概念

老鸟:简单来说,工厂方法模式是一种创建对象的设计模式。它将对象的创建过程封装在一个工厂类中,而不是在代码中直接使用构造函数。举个生活中的例子,想象你去了一家餐馆点餐。你不会亲自去厨房做饭,而是告诉服务员你要什么,然后服务员帮你把饭菜准备好。这就类似于工厂方法模式。

菜鸟:哦,有点明白了。也就是说,工厂方法模式可以帮我们把对象的创建过程封装起来,对吧?

老鸟:没错!它的核心思想就是将对象的创建延迟到子类中,让子类决定要创建的对象类型。

Python代码示例,逐步展开

菜鸟:那我们用代码来看看吧。

老鸟:好的,先从一个简单的例子开始。假设我们有一个 Product 类和它的两个子类 ConcreteProductAConcreteProductB

class Product:
    def operation(self):
        pass

class ConcreteProductA(Product):
    def operation(self):
        return "Result of ConcreteProductA"

class ConcreteProductB(Product):
    def operation(self):
        return "Result of ConcreteProductB"

菜鸟:看起来很简单。那我们怎么用工厂方法模式来创建这些对象呢?

老鸟:首先,我们定义一个工厂基类 Creator,它有一个创建产品的方法 create_product。然后,我们定义具体的工厂子类 ConcreteCreatorAConcreteCreatorB,它们分别创建 ConcreteProductAConcreteProductB

class Creator:
    def create_product(self):
        pass

class ConcreteCreatorA(Creator):
    def create_product(self):
        return ConcreteProductA()

class ConcreteCreatorB(Creator):
    def create_product(self):
        return ConcreteProductB()

菜鸟:哦,我明白了。这样我们就可以通过工厂子类来创建不同的产品对象了。

老鸟:没错。来看看完整的例子。

# 产品类及其子类
class Product:
    def operation(self):
        pass

class ConcreteProductA(Product):
    def operation(self):
        return "Result of ConcreteProductA"

class ConcreteProductB(Product):
    def operation(self):
        return "Result of ConcreteProductB"

# 工厂基类及其子类
class Creator:
    def create_product(self):
        pass

class ConcreteCreatorA(Creator):
    def create_product(self):
        return ConcreteProductA()

class ConcreteCreatorB(Creator):
    def create_product(self):
        return ConcreteProductB()

# 客户端代码
def client_code(creator: Creator):
    product = creator.create_product()
    print(f"Client: {product.operation()}")

if __name__ == "__main__":
    print("App: Launched with ConcreteCreatorA.")
    client_code(ConcreteCreatorA())

    print("App: Launched with ConcreteCreatorB.")
    client_code(ConcreteCreatorB())

菜鸟:这很有趣。但是,直接实例化工厂子类和直接使用构造函数有何区别呢?

问题与反思

老鸟:这是个好问题。直接使用构造函数时,客户端代码依赖于具体类,这会导致代码耦合度高。而使用工厂方法模式,客户端代码依赖于抽象的工厂类,具体的产品创建逻辑被封装在工厂子类中,这样可以降低代码的耦合度,提高可维护性。

菜鸟:明白了。这样当我们需要添加新产品时,只需要添加新的工厂子类和产品子类,而无需修改客户端代码。

老鸟:正是如此。

优势与适用场景

老鸟:工厂方法模式的优势在于:

  1. 降低耦合度:客户端代码依赖于抽象的工厂类,而不是具体的产品类。
  2. 提高可扩展性:添加新产品时,只需要添加新的工厂子类和产品子类,无需修改现有代码。
  3. 遵循开闭原则:扩展新的功能时,不需要修改现有代码,减少了错误风险。

菜鸟:那它适用于哪些场景呢?

老鸟:工厂方法模式适用于以下场景:

  1. 当一个类不知道它所需要的对象的类时
  2. 当一个类希望由其子类来指定创建的对象时
  3. 当类将创建对象的职责委托给多个帮助子类中的某一个时,并希望将哪一个子类是代理者这一信息局部化时

常见误区与优化建议

老鸟:不过,使用工厂方法模式时也要注意一些常见误区:

  1. 滥用模式:工厂方法模式适用于特定场景,不要为了使用而使用。
  2. 复杂性增加:对于简单对象创建,不必使用工厂方法模式,避免不必要的复杂性。

菜鸟:明白了,那有没有什么优化建议呢?

老鸟:优化建议包括:

  1. 明确需求:在决定使用工厂方法模式前,明确你的需求和问题。
  2. 结合其他模式:有时可以结合其他设计模式,如抽象工厂模式来进一步优化设计。

总结与延伸阅读

老鸟:今天我们讨论了工厂方法模式,包括它的定义、优势、适用场景以及常见误区。希望通过这些内容,你对工厂方法模式有了更深的理解。

菜鸟:非常感谢,老鸟!我学到了很多。

老鸟:不客气。如果你感兴趣,接下来可以学习一下其他设计模式,如单例模式和抽象工厂模式。推荐阅读《设计模式:可复用面向对象软件的基础》这本书,对理解设计模式非常有帮助。

菜鸟:好的,我会去看看这本书。谢谢你的指导!

老鸟:祝你学习愉快!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2114929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据集 3DPW-开源户外三维人体建模-姿态估计-人体关键点-人体mesh建模 >> DataBall

3DPW 3DPW-开源户外三维人体建模数据集-姿态估计-人体关键点-人体mesh建模 开源户外三维人体数据集 inproceedings{vonMarcard2018, title {Recovering Accurate 3D Human Pose in The Wild Using IMUs and a Moving Camera}, author {von Marcard, Timo and Henschel, Robe…

从“游戏科学”到玄机科技:《黑神话:悟空》的视角打开动漫宇宙

近日,中国游戏界迎来了一场前所未有的盛事——由游戏科学公司开发的《黑神话:悟空》正式上线,并迅速成为全球玩家热议的焦点。在居高不下的讨论热度中,有人说他的成功在于对《西游记》为背景进行改编,对原著进行了分析…

读软件设计的要素04概念的关系

1. 概念的关系 1.1. 概念是独立的,彼此间无须相互依赖 1.1.1. 一个概念是应该独立地被理解、设计和实现的 1.1.2. 独立性是概念的简单性和可重用性的关键 1.2. 软件存在依赖性 1.2.1. 不是说一个概念需要依赖另一个概念才能正确运行 1.2.2. 只有当一个概念存在…

1 模拟——67. 二进制求和

1 模拟 67. 二进制求和 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 示例 1: 输入:a "11", b "1" 输出:"100" 示例 2: 输入:a "1010", b "…

单GPU一分钟生成16K高清图像!新加坡国立发布LinFusion:无缝兼容Stable Diffusion插件

论文链接:https://arxiv.org/pdf/2409.02097 Git链接:https://lv-linfusion.github.io/ 亮点直击 本文研究了Mamba的非因果和归一化感知版本,并提出了一种新颖的线性注意力机制,解决了扩散模型在高分辨率视觉生成中的挑战。 本文…

Vue——day11之生命周期

目录 生命周期的八个阶段 生命周期执行的流程图 代码示例 总结 Vue的生命周期是指在Vue实例创建、挂载、更新和销毁过程中,会触发的一系列钩子函数。这些钩子函数可以用来在不同的生命周期阶段执行相应的逻辑操作。 生命周期的八个阶段 Vue的生命周期可以分为…

Github 2024-09-08 php开源项目日报 Top10

根据Github Trendings的统计,今日(2024-09-08统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量PHP项目10TypeScript项目1JavaScript项目1Laravel: 以优雅语法简化Web开发 创建周期:4028 天开发语言:PHP协议类型:MIT LicenseStar数量:30…

gazebo 已加载模型但无法显示

目录 写在前面的话问题一:robot_state_publisher 发布机器人信息失败报错一 Error: Error document empty.报错二 .xcaro 文件中有多行注释成功启动 问题二:通过 ros2 启动 gazebo 失败成功启动 问题三:gazebo 崩溃和无法显示模型问题四&…

使用LSTM(长短期记忆网络)模型预测股票价格的实例分析

一:LSTM与RNN的区别 LSTM(Long Short-Term Memory)是一种特殊的循环神经网络(RNN)架构。LSTM是为了解决传统RNN在处理长序列数据时遇到的梯度消失或梯度爆炸问题而设计的。 在传统的RNN中,信息通过隐藏状…

电动机制造5G智能工厂工业物联数字孪生平台,推进制造业数字化转型

电动机制造5G智能工厂工业物联数字孪生平台,推进制造业数字化转型。5G智能工厂与物联数字孪生平台的融合应用,为电动机制造业的数字化转型铺设了一条高速通道。这一创新模式不仅极大地提升了生产效率,还深刻改变了产品的设计、生产、管理及运…

在全球化时代成为超级个体:Web3、个人品牌与AI工具的融合

随着Web3技术和人工智能的快速发展,个人品牌建设与创作者经济正在迎来前所未有的机遇。《Web3Brand》是一个专注于帮助用户理解Web3技术、建立和增强个人品牌、提升创作者经济实力,并利用AI工具提高工作效率的平台。本文将探讨该博客如何通过提供播客、案例分析、策略指南和工…

redis内存清理和linux系统清理缓存以及redis启动

1清空所有数据库 redis-cli FLUSHALL 2清空所有数据库redis-cli FLUSHDB 3. 删除指定的缓存键 redis-cli DEL <key>4. 设置键过期 redis-cli EXPIRE <key> <seconds>例如&#xff1a; redis-cli EXPIRE mykey 605.启动redis 这个启动命令要在/usr/loca…

sql 中名字 不可以 包含 mysql中 具有 特定意义 的单词

这种sql执行不报错 这种sql执行报错 所以sql中名字不可以使用mysql中具有特定意义的单词 以此文章作为警告&#xff0c;我下次起名字不可以使用 mysql中具有特殊意义的字符 就因为这个导致我搞了一个多小时&#xff0c;急死我了&#xff0c;周五就要前后端联调了。下次千万不…

NSmartProxy:一款.NET开源、跨平台的内网穿透工具

前言 今天大姚给大家分享一款.NET开源、免费&#xff08;MIT License&#xff09;、跨平台的内网穿透工具&#xff0c;采用.NET Core的全异步模式打造&#xff1a;NSmartProxy。 内网穿透工具介绍 内网穿透工具是一种能够允许用户从互联网上的任何地方安全地访问并管理处于内…

代码随想录训练营day37|52. 携带研究材料,518.零钱兑换II,377. 组合总和 Ⅳ,70. 爬楼梯

52. 携带研究材料 这是一个完全背包问题&#xff0c;就是每个物品可以无限放。 在一维滚动数组的时候规定了遍历顺序是要从后往前的&#xff0c;就是因为不能多次放物体。 所以这里能多次放物体只需要把遍历顺序改改就好了 # include<iostream> # include<vector>…

数据结构:线性表的顺序存储

文章目录 &#x1f34a;自我介绍&#x1f34a;线性表的顺序存储介绍概述例子 &#x1f34a;顺序表的存储类型设计设计思路类型设计 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以&#xff1a;点赞关注评论收藏&#xff08;一键四连&#xff09;哦~ &#x1f34a;自我…

Temu官方宣导务必将所有的点位材料进行检测-RSL资质检测

关于饰品类产品合规问题宣导&#xff1a; 产品法规RSL要求 RSL测试是根据REACH法规及附录17的要求进行测试。REACH法规是欧洲一项重要的法规&#xff0c;其中包含许多对化学物质进行限制的规定和高度关注物质。 为了确保珠宝首饰的安全性&#xff0c;欧盟REACH法规规定&#…

【H2O2|全栈】关于HTML(2)HTML基础(一)

HTML相关知识 目录 前言 准备工作 标签的具体分类&#xff08;一&#xff09; 本文中的标签在什么位置使用&#xff1f; 属性 标题标签 段落标签 文本格式化标签 分类汇总 计算机输出标签 ​编辑分类汇总 引文&#xff0c;引用标签 分类汇总 预告和回顾 UI设计…

SAP学习笔记 - 开发04 - Fiori UI5 开发环境搭建

上一章学习了 CDSView开发环境的搭建&#xff0c;以及CDSView相关的知识。 SAP学习笔记 - 开发03 - CDSView开发环境搭建&#xff0c;Eclipse中连接SAP&#xff0c;CDSView创建-CSDN博客 本章继续学习SAP开发相关的内容&#xff0c; - Fiori UI5的开发环境搭建 - 安装VSCode …

JavaScript Web API入门day7

目录 1.图片切换模块 2.鼠标经过以及离开中等盒子&#xff0c;大盒子的处理 3.黑色遮罩层的位置以及放大功能 4.放大镜的完整代码 1.图片切换模块 效果图&#xff1a; 思路分析&#xff1a; ①&#xff1a;鼠标经过小盒子&#xff0c;左侧中等盒子显示对应中等图片 获取对…