当前位置: 首页 > news >正文

java设计模式学习之【工厂模式】

文章目录

  • 引言
  • 工厂方法模式简介
    • 定义与用途:
    • 实现方式:
  • 使用场景
  • 优势与劣势
  • 工厂模式在spring中的应用
  • 电费计算示例(简单工厂模式)
  • 改善为方法工厂模式
  • 代码地址

引言

在软件开发的世界中,对象的创建可能是一个复杂且重复的过程。为了简化这个过程,设计模式中的“工厂方法”就像一个小工厂,专门负责生产特定类型的对象。今天,我们来深入探索这个设计模式,看看它是如何让对象的创建变得简单又有趣。

工厂方法模式简介

工厂方法模式是一种创建型设计模式。 它通过使用一个工厂类来创建对象,而不是直接使用 new 运算符。这使得程序可以在不知道对象确切类型的情况下,生成对象的实例。

定义与用途:

  1. 工厂设计模式是一种创建型设计模式,广泛应用于JDK和像Spring、Struts这样的框架中。
  2. 当有一个超类和多个子类,并且基于输入返回其中一个子类时,使用工厂设计模式是非常合适的。

实现方式:

通过将类的实例化过程从客户端代码转移到工厂类,从而减少客户端的复杂性。

使用场景

  • 当类的实例化过程复杂,需要依据不同的条件来创建不同的对象时。
  • 当需要解耦对象的创建和使用时。
  • 在提供一个类库,并希望只暴露接口而非实现细节时。

优势与劣势

  • 优势
    提高灵活性:可以在运行时选择创建哪个类的实例。
    降低耦合度:客户端代码与具体类的创建过程解耦。
    易于扩展:添加新的类不影响现有代码。
  • 劣势
    增加代码复杂性:可能会引入许多新类,增加系统的复杂性。
    维护难度:当添加新类型时,可能需要修改工厂类。

工厂模式在spring中的应用

Spring框架广泛地应用了工厂模式,这是Spring框架中对象管理和依赖注入核心功能的基础。以下是Spring框架中使用工厂模式的几个关键地方:

BeanFactory:
Spring框架中最基本的容器,它提供了依赖注入(DI)的支持。
BeanFactory 使用工厂模式来实例化应用程序中的所有bean。
它使用 getBean 方法来创建bean实例。ApplicationContext:
它是 BeanFactory 的子接口,提供了更高级的特性,如事件传播、资源加载等。
ApplicationContext 本身也是一个大型工厂,用于创建并管理应用程序中的beans,以及提供对不同类型的bean的访问。FactoryBean:
Spring中特殊的bean类型,用于产生其他bean实例。
这种模式允许用户实现复杂的初始化逻辑,并通过Spring容器进行管理。BeanDefinition:
在Spring中,BeanDefinition 代表了bean的配置元数据,它将如何在Spring容器中创建bean的细节描述了出来。
通过这种方式,Spring使用工厂模式来创建具体的bean实例。单例模式与工厂模式的结合:
默认情况下,Spring容器中的所有bean都是单例的,这意味着每个bean都是全局唯一的并且在整个应用程序中共享。
Spring容器作为工厂,管理着这些单例bean的生命周期和实例化过程。依赖注入(DI):
虽然DI不是工厂模式,但它利用了工厂模式的概念来实现对象的创建和依赖的注入。
DI容器(如 Ap	plicationContext)负责创建对象和管理它们的依赖关系,这在本质上是一种工厂模式的应用。

电费计算示例(简单工厂模式)

我们将创建一个名为 Plan 的抽象类以及继承该抽象类的具体类。下一步是定义一个名为 GetPlanFactory 的工厂类。
GenerateBill 类将使用 GetPlanFactory 来获取一个 Plan 对象。它将传递信息(DOMESTICPLAN / COMMERCIALPLAN / INSTITUTIONALPLAN)给 GetPlanFactory,以获取它所需的对象类型。
在这里插入图片描述

步骤 1: 创建抽象计划类
首先,我们定义一个抽象类 Plan,它包含了计算电费所必需的方法和属性。

abstract class Plan {protected double rate;abstract void getRate();public void calculateBill(int units) {System.out.println(units * rate);}
} //end of Plan class.

步骤 2: 定义具体计划类
接着,我们创建具体类 DomesticPlan、CommercialPlan 和 InstitutionalPlan,这些类继承自 Plan 并提供了 getRate 方法的具体实现。

class DomesticPlan extends Plan {public void getRate() {rate = 3.50;}
} //end of DomesticPlan class.class CommercialPlan extends Plan {public void getRate() {rate = 7.50;}
} //end of CommercialPlan class.class InstitutionalPlan extends Plan {public void getRate() {rate = 5.50;}
} //end of InstitutionalPlan class.

步骤 3: 创建工厂类
GetPlanFactory 是一个工厂类,根据传入的计划类型生成相应的计划对象。

class GetPlanFactory {public Plan getPlan(String planType) {if (planType == null) {return null;}if (planType.equalsIgnoreCase("DOMESTICPLAN")) {return new DomesticPlan();} else if (planType.equalsIgnoreCase("COMMERCIALPLAN")) {return new CommercialPlan();} else if (planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {return new InstitutionalPlan();}return null;}
} //end of GetPlanFactory class.

步骤 4: 生成账单
GenerateBill 类使用 GetPlanFactory 来获取具体的计划对象,并根据使用的单位数计算电费。

class GenerateBill {public static void main(String args[]) throws IOException {GetPlanFactory planFactory = new GetPlanFactory();BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.print("Enter the name of plan for which the bill will be generated: ");String planName = br.readLine();System.out.print("Enter the number of units for bill will be calculated: ");int units = Integer.parseInt(br.readLine());Plan p = planFactory.getPlan(planName);System.out.print("Bill amount for " + planName + " of " + units + " units is: ");p.getRate();p.calculateBill(units);}
} //end of GenerateBill class.

以上就是一个简单的工厂模式示例代码,运行代码我们可以看到:
输入相应的计划就可以算出该类型下具体的电费。
在这里插入图片描述

改善为方法工厂模式

当新的计划类型增加时,GetPlanFactory 就需要修改。这违反了开闭原则(对扩展开放,对修改封闭)。
以上举例属于简单工厂模式接下来改为方法工厂模式。

改造步骤

  • 创建一个抽象的工厂类或接口。
  • 为每种计划类型创建具体的工厂类,继承自抽象工厂类或实现工厂接口。
  • 每个具体工厂类实现创建相应产品对象的方法。
public abstract class GetPlanFactoryPro {abstract Plan getPlan();
}class DomesticPlanFactory extends GetPlanFactoryPro {@OverridePlan getPlan() {return new DomesticPlan();}
}class CommercialPlanFactory extends GetPlanFactoryPro {@OverridePlan getPlan() {return new CommercialPlan();}
}class InstitutionalPlanFactory extends GetPlanFactoryPro {@OverridePlan getPlan() {return new InstitutionalPlan();}
}

调用方法:

public class GenerateBillPro {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.print("Enter the name of plan for which the bill will be generated: ");String planName = br.readLine();System.out.print("Enter the number of units for bill will be calculated: ");int units = Integer.parseInt(br.readLine());GetPlanFactoryPro factory = getFactory(planName);if (factory == null) {System.out.println("Invalid Plan Type");return;}Plan p = factory.getPlan();System.out.print("Bill amount for " + planName + " of " + units + " units is: ");p.getRate();p.calculateBill(units);}private static GetPlanFactoryPro getFactory(String planType) {if (planType.equalsIgnoreCase("DOMESTICPLAN")) {return new DomesticPlanFactory();} else if (planType.equalsIgnoreCase("COMMERCIALPLAN")) {return new CommercialPlanFactory();} else if (planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {return new InstitutionalPlanFactory();}return null;}}

**灵活性和扩展性:**通过使用工厂方法模式,我们增加了代码的灵活性和扩展性。如果要添加新的计划类型,只需增加一个新的工厂类,而无需修改现有的工厂逻辑或客户端代码。
**符合开闭原则:**工厂方法模式使得我们的代码更好地符合开闭原则,因为现在系统可以在不修改现有代码的情况下引入新类型的Plan。

缺点:
随着产品类的增加,相关的工厂类也会增加,可能导致系统类的数量增长。

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

相关文章:

java设计模式学习之【工厂模式】

文章目录 引言工厂方法模式简介定义与用途:实现方式: 使用场景优势与劣势工厂模式在spring中的应用电费计算示例(简单工厂模式)改善为方法工厂模式代码地址 引言 在软件开发的世界中,对象的创建可能是一个复杂且重复的…...

android 内存分析(待续)

/proc/meminfo memory状态解读 命令:adb shell cat /proc/meminfo内存分布log 查看方式 命令:adb shell cat /proc/meminfo 用途:可以整体的了解memory使用情况 我们说的可用memory一般以MemAvailable的数据为准。所以了解MemAvailable的组成可以帮助…...

2023-简单点-机器学习中的数值计算问题

上溢和下溢: 上溢:指数函数或对数函数的输入值过大,导致计算结果超出了计算机可以表示的最大值。例如,在softmax函数中,当输入的数值很大时,指数运算的结果可能非常大,导致上溢。 下溢&#x…...

Qt5的事件处理函数有哪些?

2023年11月29日,周三上午 通过查看QWidget的定义可知,事件处理函数有: bool event(QEvent *event) override;virtual void mousePressEvent(QMouseEvent *event);virtual void mouseReleaseEvent(QMouseEvent *event);virtual void mouseDou…...

Jmeter性能综合实战——签到及批量签到

提取性能测试的三个方面:核心、高频、基础功能 签 到 请 求 步 骤 1、准备工作: 签到线程组 n HTTP请求默认值 n HTTP cookie 管理器 n 首页访问请求 n 登录请求 n 查看结果树 n 调试取样器 l HTTP代理服务器 (1)创建线…...

04 # 第一个 TypeScript 程序

初始化项目以及安装依赖 新建 ts_in_action 文件夾 npm init -y安装好 typescript,就可以执行下面命令查看帮助信息 npm i typescript -g tsc -h创建配置文件,执行下面命令就会生成一个 tsconfig.json 文件 tsc --init使用 tsc 编译一个 js 文件 新…...

Android gradle 配置阿里镜像

要在Android Gradle中配置阿里镜像,可以按照以下步骤进行操作: 打开项目中的 build.gradle 文件。 在 build.gradle 文件中添加阿里镜像的地址,如下所示: buildscript {repositories {maven { url https://maven.aliyun.com/re…...

Arduino驱动DHT20温湿度传感器(温湿度传感器)

目录 1、传感器特性 2、硬件原理图 3、控制器和传感器连线图 4、驱动程序 DHT20温湿度传感器是DHT11的全新升级版。 DHT20采用全新的ASIC专用芯片、改进的MEMS半导体电容式湿度传感器元件和标准片上温度元件。所有传感器均经过工厂校准,具有低功耗、高精度和稳定性、响应…...

如何使用ArcGIS Pro制作一张北极俯视地图

地图的表现形式有很多种,经常我们看到的地图是以大西洋为中心的地图,还有以太平洋为中心的地图,今天要给大家介绍的地图是从北极上方俯视看的地图,这里给大家讲解一下制作方法,希望能对你有所帮助。 修改坐标系 制作…...

每天五分钟计算机视觉:经典架构的力量与启示

在深度学习和计算机视觉领域,卷积神经网络(Convolutional Neural Networks,简称CNN)无疑是最为经典的架构之一。近年来,随着研究的不断深入和新架构的不断涌现,许多初学者可能会忽视这些经典架构的重要性。然而,理解并学习这些经典架构,对于我们深入理解卷积神经网络的…...

element plus 使用细节

菜鸟一直在纠结这个写不写,因为不难,但是菜鸟老是容易忘记,虽然想想或者搜搜就可以马上写出来,但是感觉每次那样就太麻烦了,不如一股做气写了算了,后面遇见别的就再来补充! 文章目录 table 表格…...

分析:为什么有些pdf打开之后无法编辑?

pdf文件大家应该都经常接触,但是不知道大家会遇到这种情况:有些PDF文件打开之后无法编辑?是什么原因呢?今天我们来分析一下都是那些原因导致的。 首先我们可以考虑一下,PDF文件中的内容是否是图片,如果确认…...

Django请求生命周期流程

浏览器发起请求。 先经过网关接口,Django自带的是wsgiref,请求来的时候解析封装,响应走的时候打包处理,这个wsgiref模块本身能够支持的并发量很少,最多1000左右,上线之后会换成uwsgi,并且还会加…...

C++学习 --string

目录 1, 什么是string 2, 创建string 3, 操作string 3-1, 赋值 3-1-1, 赋值() 3-1-1, 赋值(assign) 3-2, 修改 3-2-1, 拼接 3-2-1-1, 拼接() 3-2-1-2&#xff…...

Spark SQL,DF,RDD cache常用方式

RDD中的cache 调用cache方法 val testRDD sc.parallelize(Seq(elementA, elementB, elementC)).map(x > (x._1, x._2)).setName("testRDD")testRDD.cache() dataframe中的cache 利用catalog以表的形式对数据进行缓存 import org.apache.spark.SparkConf impo…...

Python中如何用栈实现队列

目录 一、引言 二、使用两个栈实现队列 三、性能分析 四、应用场景 五、代码示例 六、优缺点总结 一、引言 队列(Queue)和栈(Stack)是计算机科学中常用的数据结构。队列是一种特殊的线性表,只允许在表的前端进行…...

python模块pyDes,DES对称加密算法库

一、简介 pyDes是一个Python模块,用于进行DES(Data Encryption Standard)加密和解密操作。DES是一种对称密钥加密算法,广泛用于数据保密和传输。 优点: 1.简单易用:pyDes模块提供了简单的接口,…...

Centos7安装配置nginx

快捷查看指令 ctrlf 进行搜索会直接定位到需要的知识点和命令讲解(如有不正确的地方欢迎各位小伙伴在评论区提意见,小编会及时修改) Centos7安装配置nginx Nginx介绍 Nginx (engine x) 是一个高性能的 HTTP 和 反向代理 服务,也…...

9.Spring 整合 Redis

引入依赖:spring-boot-starter-data-redis配置 Redis:配置数据库参数、编写配置类,构造 RedisTemplate访问 Redis: redisTemplate.opsForValue() redisTemplate.opsForHash() redisTemplate.opsForList() redisTemplate.opsForSe…...

【Java学习笔记】73 - 正则表达式

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter27/src/com/yinhai/regexp 一、引入正则表达式 1.提取文章中所有的英文单词 2.提取文章中所有的数字 3.提取文章中所有的英文单词和数字 4.提取百度热榜标题 正则表达式是处理文本的利器…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Map相关知识

数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦&#xff0…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

LangFlow技术架构分析

🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...