【设计模式】创建型设计模式之 工厂模式

一、介绍

工厂模式可以分为 3 个小类

  1. 简单工厂模式
  2. 工厂方法模式
  3. 抽象工厂模式

工厂模式的工厂类,并不一定以 Factory 结尾,例如 DataFormat、Calender 他们都是工厂类,通过静态方法来创建实例。

除此之外,创建对象的方法名称一般是 create+类名,但是也有其他的命名方式例如 getInstance()、createInstance() createInstance() ,甚至是 valueOf 也是工厂的方法例如 String 的 valueOf()方法。


二、简单工厂模式

介绍

image.png

  1. 将创建对象的函数,从代码中剥离并且将其放到一个独立的类中。让这个类只负责对象的创建。那这个类就是简单工厂模式的工厂类。
  2. 虽然大部分的工厂模式的结尾都是 Factory,但是不是必须的,例如 Java 中的 DateFormat、Calender 尽管没有以 Factory 但是他们也是工厂类。甚至 String.valueOf 也是工厂类。

自定义案例代码

// 定义 Shape 接口
interface Shape {void draw();
}// 具体形状类:圆形
class Circle implements Shape {@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}// 具体形状类:矩形
class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}// 简单工厂类,用于创建形状对象
class ShapeFactory {// 使用 getShape 方法获取形状类型的对象public static Shape getShape(String shapeType) {if (shapeType == null) {return null;} else if (shapeType.equalsIgnoreCase("CIRCLE")) {return new Circle();} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {return new Rectangle();}return null;}
}// 客户端代码
public class SimpleFactoryPatternDemo {public static void main(String[] args) {// 获取形状类型的对象Shape shape1 = ShapeFactory.getShape("CIRCLE");// 调用 Circle 的 draw 方法shape1.draw();Shape shape2 = ShapeFactory.getShape("RECTANGLE");// 调用 Rectangle 的 draw 方法shape2.draw();// 请求一个不支持的形状类型Shape shape3 = ShapeFactory.getShape("SQUARE");if (shape3 != null) {shape3.draw();} else {System.out.println("Shape not supported.");}}
}

第二类简单工厂

如果将简单工厂模式和类似的单例模式组合起来,那么可以称之为第二类简单工厂模式

public class ReleConfigParseFactory{private static final Map<String,RuleConfigParse> rulesMap=new HashMap<>();static{rulesMap.put(XXXX)}public static getParse(String name){return relesMap.get(name);}
}



三、工厂方法模式

  1. 简单工厂模式如果要新增产品类型则需要在工厂类中新增 不够符合开闭原则
  2. 工厂方法模式 对于新增一个具体的产品来说,只需要新增一个工厂类更符合开闭原则。
  3. 在业务中创建工厂类仍然负责,所以可以结合简单工厂。对于具体的 FactoryABC 再创建一个简单工厂也就是工厂的工厂。这样新增工厂类后,只需要在工厂的工厂中添加该工厂而不需要大量的改动。

缺点:

  1. 工厂类只包含一个创建代码,功能单薄有点过度设计。如果代码足够简单,应该使用简单工厂模式。



四、抽象工厂模式


如果具体需要创建的对象包含多种分类,那么实用工厂方法模式可能会产生大量的工厂类。
例如上图,包含两种产品 Computer 和 Phone ,同事包含两个厂商 小米和苹果,如果使用工厂方法则会产生四个工厂。
引入抽象工厂模式后,AppleFactory 和 MiFactory 每个工厂负责多种类型的产品可以有效减少对应工厂的个数。



五、总结

使用工厂模式的场景

场景 1:代码中存在根据不同条件创建不同对象的代码,可以考虑使用工厂模式将这一大段代码进行抽离。如果每个对象的创建都比较简单那么就使用简单工厂模式,如果对象的创建过程比较负责责使用工厂方法模式将每个对象的创建过程封装到各自的工厂类中。
**场景 2:**一个类的对象创建比较复杂,例如涉及其他的对象,复杂的初始化逻辑等。也可以考虑使用工厂模式,将对象创建的过程封装到工厂模式中。
工厂模式作用总结:

可以根据下面四条规则判断是否使用工厂模式

  1. 封装变化 利用工厂模式封装创建逻辑,创建逻辑的变更对调用者透明。
  2. 代码复用 避免业务中创建对象的代码散落各处,避免重复编写。
  3. 隔离复杂性:封装复杂的创建逻辑,让使用者无需关注具体的创建细节。
  4. 控制复杂度:将创建逻辑与使用逻辑分离,简化代码。

开发中常见的工厂模式案例

  1. DateFormat、Calendar 类
  2. 日志工厂 LoggerFactory 经常使用工厂模式来创建日志记录器(Logger)实例。开发者可以通过工厂方法请求一个日志记录器,而不需要知道具体实现细节。这样可以在不修改应用程序代码的情况下,灵活切换日志框架。
  3. Spring 这种 DI 框架,例如 BeanFactory 管理着对象的声明周期,也作为对象的创建工厂

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django与MySQL:配置数据库的详细步骤

文章目录 Django-MySQL 配置配置完执行数据迁移&#xff0c;如果报错: Error loading MySQLdb module&#xff0c; Django-MySQL 配置 # settings.pyDATABASES {# 默认配置sqlite3数据库# default: {# ENGINE: django.db.backends.sqlite3,# NAME: BASE_DIR / db.sqli…

PHP质量工具系列之phpmd

PHPMD PHP Mess Detector 它是PHP Depend的一个衍生项目&#xff0c;用于测量的原始指标。 PHPMD所做的是&#xff0c;扫描项目中可能出现的问题如&#xff1a; 可能的bug次优码过于复杂的表达式未使用的参数、方法、属性 PHPMD是一个成熟的项目&#xff0c;它提供了一组不同的…

使用 ML.NET CLI 自动进行模型训练

ML.NET CLI 可为 .NET 开发人员自动生成模型。 若要单独使用 ML.NET API(不使用 ML.NET AutoML CLI),需要选择训练程序(针对特定任务的机器学习算法的实现),以及要应用到数据的数据转换集(特征工程)。 每个数据集的最佳管道各不相同,从所有选择中选择最佳算法增加了复…

深度解析:ChatGPT全面测评——功能、性能与用户体验全景剖析

从去年底至今&#xff0c;由 OpenAI 发布的大规模语言模型 ChatGPT 引发了几乎所有科技领域从业者的高度关注。据瑞银集团的报告显示&#xff0c;自 2023 年 1 月起&#xff0c;仅两个月内&#xff0c;ChatGPT 的月活用户数便超过了 1 亿。 ChatGPT 被誉为“最强 AI”&#xff…

【Spring6】1-12章源码级深入详解 IoC

一、Spring启示录 阅读以下代码&#xff1a; package com.powernode.oa.controller;import com.powernode.oa.service.UserService; import com.powernode.oa.service.impl.UserServiceImpl;public class UserController {private UserService userService new UserServiceI…

C# MES通信从入门到精通(11)——C#如何使用Json字符串

前言 我们在开发上位机软件的过程中&#xff0c;经常需要和Mes系统进行数据交互&#xff0c;并且最常用的数据格式是Json&#xff0c;本文就是详细介绍Json格式的类型&#xff0c;以及我们在与mes系统进行交互时如何组织Json数据。 1、在C#中如何调用Json 在C#中调用Json相关…

项目:双人五子棋对战-对战模块(6)

完整代码见: 邹锦辉个人所有代码: 测试仓库 - Gitee.com 当玩家进入到游戏房间后, 就要开始一局紧张而又刺激的五子棋对战了, 本文将就前端后端的落子与判断胜负的部分作详细讲解. 模块详细讲解 约定前后端交互的接口 首先是建立连接后, 服务器需要生成一些游戏的初始信息(可…

java:FeignClient通过RequestInterceptor自动添加header

示例代码 【pom.xml】 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.12.RELEASE</version> </dependency> <dependency><groupId>o…

pytorch 自定义学习率更新 Poly

Poly 学习率调整策略需要继承_LRScheduler类&#xff0c;该类包含三个重要属性和两个重要方法 学习率与batch-size的关系 一般来说&#xff0c;batch-size的大小一般与学习率的大小成正比。batch-size越大一般意味着算法收敛方向的置信度越大&#xff0c;也可以选择较大的学…

【课程总结】Day6(下):机器学习项目实战–成人收入预测

机器学习项目实战&#xff1a;成人收入预测 项目目的 基于个人收入数据(包括教育程度、年龄、性别等)的数据集&#xff0c;通过机器学习算法&#xff0c;预测一个人的年收入是否超过5万美金。 数据集 地址&#xff1a;http://idatascience.cn/dataset-detail?table_id10036…

MEGALODON:突破传统,实现高效无限上下文长度的大规模语言模型预训练和推理

在人工智能领域&#xff0c;尤其是在自然语言处理&#xff08;NLP&#xff09;中&#xff0c;大模型&#xff08;LLMs&#xff09;的预训练和推理效率一直是研究的热点。最近&#xff0c;一项突破性的研究提出了一种新型神经网络架构——MEGALODON&#xff0c;旨在解决传统Tran…

2024/06/11--代码随想录算法1/17|理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

理论基础 动态规划&#xff1a;当前状态由前面的状态推导而来 贪心&#xff1a;局部选最优 动态规划5步曲 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 509. 斐波那契数 力扣链接 动态规划5步曲 确定d…

33.星号三角阵(二)

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/742 题目描述 给定一个整数 𝑛,输出一个…

Linux用户,用户组,所有者权限分配,sftp用户权限分配

注意以下命令执行需要在root用户下执行 tenant命令切换至root命令 sudo -do root 删除用户信息 1.不删除用户主目录 userdel user_name 2.删除用户主目录 userdel -r user_name usermod命令修改用户账户权限 更改用户名 sudo usermod -l newusername oldusername 更…

QNX 7.0.0开发总结

1 QNX编译 1.1 基本概念 QNX可以直接使用Linux Makefile编译库和二进制&#xff0c;在Makefile文件中指定CCaarch64-unknown-nto-qnx7.0.0-g&#xff0c;或者CCx86_64-pc-nto-qnx7.0.0-g&#xff0c;保存退出后&#xff0c;运行source /qnx_sdk_path/qnxsdp-env.sh&#xff0c;…

React+TS前台项目实战(四)-- layout整体布局搭建

文章目录 前言一、Layout组件代码注释说明二、Content全局组件注释说明三、Header基础布局组件1. Header父级组件注释说明2. NavMenu导航子组件详细说明 四、效果展示总结 前言 本文主要讲Layout整体布局的构建以及全局内容盒子Content组件的使用。还包括了导航栏组件的基本封…

实现开源可商用的 ChatPDF RAG:密集向量检索(R)+上下文学习(AG)

实现 ChatPDF & RAG&#xff1a;密集向量检索&#xff08;R&#xff09;上下文学习&#xff08;AG&#xff09; RAG 是啥&#xff1f;实现 ChatPDF怎么优化 RAG&#xff1f; RAG 是啥&#xff1f; RAG 是检索增强生成的缩写&#xff0c;是一种结合了信息检索技术与语言生成…

python之点云数据读取与可视化

1、前言 将文件中点云数据进行读取进来&#xff0c;并进行数据处理&#xff0c;将处理后的点云数据进行可视化显示&#xff0c;是非常常见的操作。本博客介绍如何将文本形式的点云数据读取进来&#xff0c;并进行可视化展示。 2、点云可视化 点云可视化即将点云数据在三维空间…

亚马逊竞品分析之如何查找竞品

初选之后,要对产品进行竞品分析,查找竞品的方法: 1.Best Seller榜单查找 进入到该类目的BS榜单去找跟你选中的产品的竞品 看完BS榜单会找出一部分竞品 这个找相似也可以点击,是插件的一个以图搜图的功能,不过有的时候不太好使,某些同款产品可能搜不到。 Edge浏览器搭…

第7章 用户输入和 while 循环

第7章 用户输入和 while 循环 7.1 函数 input()的工作原理7.1.1 编写清晰的程序7.1.2 使用 int()来获取数值输入7.1.3 求模运算符 7.2 while 循环简介7.2.1 使用 while 循环7.2.2 让用户选择何时退出7.2.3 使用标志7.2.4 使用 break 退出循环7.2.5 在循环中使用 continue7.2.6 …