java 设计模式 工厂模式

什么是工厂模式

工厂模式(Factory Pattern)是一种创建型设计模式,它通过定义一个接口或抽象类来创建对象,但由子类决定具体实例化哪个类。简单来说,工厂模式将对象的实例化过程封装起来,客户端通过工厂方法来创建对象,而不需要直接使用 new 关键字。

工厂模式的目的是将对象的创建和使用解耦,使得客户端代码不需要关心具体对象的创建过程,尤其是对象的构造方式或者具体类型。

工厂模式的作用

  1. 解耦:客户端代码与具体的对象创建解耦,客户端只需要依赖工厂接口而不依赖具体的实现类。
  2. 代码重用:工厂方法可以提供统一的创建对象的逻辑,从而避免重复代码。
  3. 更好的扩展性:如果系统中需要新增不同的产品类,只需要添加新的工厂类即可,不需要修改原有的客户端代码。
  4. 灵活的对象管理:有些工厂模式可以实现对象的缓存或对象池,从而优化性能。

示例

不使用工厂模式获取实例

// 抽象产品:Button(按钮)
interface Button {void render();
}// 具体产品:WindowsButton(Windows 按钮)
class WindowsButton implements Button {@Overridepublic void render() {System.out.println("Rendering a Windows Button");}
}// 具体产品:MacButton(Mac 按钮)
class MacButton implements Button {@Overridepublic void render() {System.out.println("Rendering a Mac Button");}
}// 客户端代码:根据操作系统类型选择不同按钮
public class Main {public static void main(String[] args) {Button button;String osType = "Windows";  // 假设从配置中获取操作系统类型if ("Windows".equalsIgnoreCase(osType)) {button = new WindowsButton();} else {button = new MacButton();}button.render();}
}

这里如果又新增一个liunx按钮 客户端又要重新修改代码

使用工厂模式

// 抽象产品:Button(按钮)
interface Button {void render();
}// 具体产品:WindowsButton(Windows 按钮)
class WindowsButton implements Button {@Overridepublic void render() {System.out.println("Rendering a Windows Button");}
}// 具体产品:MacButton(Mac 按钮)
class MacButton implements Button {@Overridepublic void render() {System.out.println("Rendering a Mac Button");}
}// 具体产品:LinuxButton(Linux 按钮)
class LinuxButton implements Button {@Overridepublic void render() {System.out.println("Rendering a Linux Button");}
}// 抽象工厂:GUIFactory
interface GUIFactory {Button createButton();
}// 具体工厂:WindowsFactory
class WindowsFactory implements GUIFactory {@Overridepublic Button createButton() {return new WindowsButton();}
}// 具体工厂:MacFactory
class MacFactory implements GUIFactory {@Overridepublic Button createButton() {return new MacButton();}
}// 具体工厂:LinuxFactory
class LinuxFactory implements GUIFactory {@Overridepublic Button createButton() {return new LinuxButton();}
}// 工厂创建器:根据操作系统类型选择对应的工厂
class FactoryCreator {public static GUIFactory getFactory(String osType) {if ("Windows".equalsIgnoreCase(osType)) {return new WindowsFactory();} else if ("Mac".equalsIgnoreCase(osType)) {return new MacFactory();} else if ("Linux".equalsIgnoreCase(osType)) {return new LinuxFactory();}return null;}
}// 客户端代码:通过工厂创建按钮
public class Main {public static void main(String[] args) {// 假设从配置文件或环境变量获取操作系统类型String osType = System.getProperty("os.name"); // 获取操作系统名称(例如:Windows、Mac、Linux)// 使用工厂创建器自动选择工厂GUIFactory factory = FactoryCreator.getFactory(osType);// 通过工厂创建按钮if (factory != null) {Button button = factory.createButton();button.render();} else {System.out.println("No suitable factory found for " + osType);}}
}

这里你无论新增多少按钮,客户端代码始终不变

工厂模式的种类

简单工厂模式(Simple Factory Pattern)

通过一个工厂类来根据参数的不同返回不同类型的对象。
优点:客户端代码很简单,所有的产品类都集中在一个地方。
缺点:如果产品类增多,工厂类需要做出改动,违反了开放-封闭原则。

示例

产品类

class Car {void drive() {System.out.println("Driving a car");}
}class Truck {void drive() {System.out.println("Driving a truck");}
}

工厂类

class VehicleFactory {public static Object createVehicle(String type) {if (type.equals("car")) {return new Car();} else if (type.equals("truck")) {return new Truck();}return null;}
}
public class Main {public static void main(String[] args) {Object vehicle = VehicleFactory.createVehicle("car");if (vehicle instanceof Car) {((Car) vehicle).drive();}}
}

工厂方法模式(Factory Method Pattern)

定义一个创建对象的接口,但让子类决定实例化哪个类。这样,工厂方法模式允许子类来决定返回什么样的对象,而不需要修改客户端代码。
优点:符合开放-封闭原则,产品扩展时不需要修改客户端代码。

简单来说,就是有个产品,咱们需要定义一个接口或者抽象类定义需要实现的方法(例如开车),然后创建多个具体类实现或者继承该方法去实现不同的开车类型(开卡车,开拖拉机,开小车),有了具体的类之后,需要创建工厂帮我们创建开车类型,这里比简单工厂模式优化点是,创建一了一个抽象工厂,让下面的子类具体工厂继承抽象工厂来帮我们实现具体的产品。这样符合开闭原则了

产品类

interface Vehicle {void drive();
}class Car implements Vehicle {@Overridepublic void drive() {System.out.println("Driving a car");}
}class Truck implements Vehicle {@Overridepublic void drive() {System.out.println("Driving a truck");}
}

工厂类

abstract class VehicleFactory {abstract Vehicle createVehicle();
}class CarFactory extends VehicleFactory {@OverrideVehicle createVehicle() {return new Car();}
}class TruckFactory extends VehicleFactory {@OverrideVehicle createVehicle() {return new Truck();}
}
public class Main {public static void main(String[] args) {VehicleFactory factory = new CarFactory();Vehicle vehicle = factory.createVehicle();vehicle.drive();}
}

抽象工厂模式

提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。
工厂方法模式创建的是单个对象,而抽象工厂模式创建的是多个相关对象。

简单来说抽象工厂就是有几个配套的抽象产品(车轮和车胎),多个具体的类实现不同的抽象产品(车轮和车胎)当成具体实现类(越野车胎,越野车轮,公路车胎,公路车轮),有了这些类之后,需要实现工厂来帮我们进行组合,所有有个抽象工厂类用来创建车胎和车轮,然后创建具体的工厂实现抽象工厂,来返回配套的车胎车轮。

示例

产品类

// 抽象产品:车轮
interface Wheel {void create();
}// 抽象产品:轮胎
interface Tire {void create();
}// 具体产品:越野车轮
class OffRoadWheel implements Wheel {@Overridepublic void create() {System.out.println("Creating Off-road Wheel");}
}// 具体产品:公路车轮
class RoadWheel implements Wheel {@Overridepublic void create() {System.out.println("Creating Road Wheel");}
}// 具体产品:越野轮胎
class OffRoadTire implements Tire {@Overridepublic void create() {System.out.println("Creating Off-road Tire");}
}// 具体产品:公路轮胎
class RoadTire implements Tire {@Overridepublic void create() {System.out.println("Creating Road Tire");}
}

工厂类

// 抽象工厂:车轮和轮胎的工厂
interface VehiclePartsFactory {Wheel createWheel();Tire createTire();
}// 具体工厂:越野车配件工厂
class OffRoadVehiclePartsFactory implements VehiclePartsFactory {@Overridepublic Wheel createWheel() {return new OffRoadWheel();}@Overridepublic Tire createTire() {return new OffRoadTire();}
}// 具体工厂:公路车配件工厂
class RoadVehiclePartsFactory implements VehiclePartsFactory {@Overridepublic Wheel createWheel() {return new RoadWheel();}@Overridepublic Tire createTire() {return new RoadTire();}
}
// 客户端代码
public class Main {public static void main(String[] args) {// 创建越野车配件工厂VehiclePartsFactory offRoadFactory = new OffRoadVehiclePartsFactory();Wheel offRoadWheel = offRoadFactory.createWheel();Tire offRoadTire = offRoadFactory.createTire();offRoadWheel.create();offRoadTire.create();// 创建公路车配件工厂VehiclePartsFactory roadFactory = new RoadVehiclePartsFactory();Wheel roadWheel = roadFactory.createWheel();Tire roadTire = roadFactory.createTire();roadWheel.create();roadTire.create();}
}

springboot哪些地方使用了工厂模式

BeanFactory 和 ApplicationContext

Spring 提供了 BeanFactory 和 ApplicationContext 作为工厂类来管理 bean 的创建和生命周期。这两个接口实际上是工厂模式的应用,ApplicationContext 扩展了 BeanFactory,用于创建和管理应用程序中的 bean。

示例

@Configuration
public class AppConfig {@Beanpublic Car car() {return new Car();}
}@SpringBootApplication
public class Main {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);Car car = context.getBean(Car.class);car.drive();}
}

FactoryBean

FactoryBean 是一个工厂类,但是它并不是直接返回一个简单的对象,而是返回一个由 FactoryBean 实现逻辑控制的复杂对象。

示例

这里可以对比之前的工厂模式,可以看出就是工厂模式(有产品类,有工厂类,有具体工厂实现)

public class Car {public void drive() {System.out.println("Driving the car!");}
}public class CarFactoryBean implements FactoryBean<Car> {@Overridepublic Car getObject() throws Exception {// 在这里可以写复杂的创建逻辑System.out.println("Creating Car object via FactoryBean");return new Car();}@Overridepublic Class<?> getObjectType() {return Car.class;}@Overridepublic boolean isSingleton() {return true;  // 返回单例}
}

JdbcTemplate

JdbcTemplate 是 Spring 中的一个工具类,它通过工厂模式封装了数据库连接的创建过程,并提供了统一的操作接口。开发者无需关心底层数据库连接的具体实现。

何时使用工厂模式?

需要隐藏对象创建的复杂性 当对象的创建过程复杂时,直接使用 new 关键字可能会导致代码重复、易出错、难以维护。通过工厂模式,可以将对象创建的过程封装到工厂类中,客户端代码不需要关心如何创建对象,而只需要关心如何使用对象。

需要创建的对象有多个子类 当你需要创建的对象有多个具体实现类,而这些类的具体实现对客户端不重要时,可以通过工厂模式来集中管理这些不同的对象创建过程。工厂模式能够根据不同的参数或条件动态决定实例化哪个具体的类。

对象的创建过程可能会变化或扩展 当系统需要支持未来扩展(例如,新增产品类或功能)时,使用工厂模式可以避免修改已有代码,只需要扩展工厂类来支持新的对象创建。工厂模式遵循 开放-封闭原则,便于扩展而不需要修改现有的客户端代码。

需要依赖注入和对象管理 在一些框架(如 Spring)中,工厂模式用于创建和管理对象,例如 BeanFactory 和 ApplicationContext 就是通过工厂模式来管理对象的生命周期和依赖关系。

简单来说

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

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

相关文章

[创业之路-248]:《华为流程变革:责权利梳理与流程体系建设》华为流程的前端拉动后端,与计算机软件的前端应用与后端程序的类比关系

华为的前端拉动后端模式与计算机前端应用与后端程序的类比关系&#xff0c;虽然两者属于不同的领域&#xff0c;但在某些方面存在有趣的相似性。以下是对这两者的类比关系的详细探讨&#xff1a; 一、华为的前端拉动后端模式 定义与特点&#xff1a; 华为的前端拉动后端模式是…

深入Node.js集群:原理、优势与搭建实战,如何应对高并发

文章目录 一、Node.js 集群简介二、Node.js 集群原理剖析2.1 主从模型2.2 负载均衡机制2.3 进程间通信&#xff08;IPC&#xff09; 三、Node.js 集群优势详解3.1 性能提升3.2 高可用性3.3 资源利用率优化 四、Node.js 集群搭建实战4.1 准备工作4.2 创建主控制节点4.3 工作节点…

数字普惠金融对新质生产力的影响研究(2015-2023年)

基于2015—2023年中国制造业上市公司数据&#xff0c;探讨了数字普惠金融对制造业企业新质生产力的影响及作用机理。研究发现&#xff0c;数字普惠金融有助于促进制造业企业新质生产力的发展&#xff0c;尤其是在数字普惠金融的使用深度较大的情况下&#xff0c;其对新质生产力…

数据仓库基础常见面试题

1.数据仓库是什么 ‌数据仓库&#xff08;Data Warehouse&#xff09;是一个面向主题的、集成的、非易失的、随时间变化的数据集合&#xff0c;用于支持企业的管理决策‌。它不同于传统的操作型数据库&#xff0c;后者主要用于处理日常业务交易和实时查询&#xff0c;而数据仓库…

记一次OpenEuler Linux磁盘分区表损坏的数据恢复

问题复现 原本有一台GIS地图服务器存放大量数据&#xff0c;突然有一天磁盘满了&#xff0c;于是运维人员照常进行磁盘扩容。但由于误操作&#xff0c;导致使用fdisk的时候把分区表损坏了&#xff0c;表现如下&#xff1a; 这里可以看到启动时能看到xvda被分为了xvda1和xvda2…

分布式数据存储基础与HDFS操作实践(副本)

以下为作者本人撰写的报告&#xff0c;步骤略有繁琐&#xff0c;不建议作为参考内容&#xff0c;可以适当浏览&#xff0c;进一步理解。 一、实验目的 1、理解分布式文件系统的基本概念和工作原理。 2、掌握Hadoop分布式文件系统&#xff08;HDFS&#xff09;的基本操作。 …

【数据结构学习笔记】19:跳表(Skip List)

介绍 跳表是一个能在 O ( n l o g n ) O(nlogn) O(nlogn)时间完成查找、插入、删除的数据结构&#xff0c;相比于树形结构优点就是很好写&#xff08;所以也用于实现Redis ZSet&#xff09;。其核心思想就是维护一个元素有序的&#xff0c;能随机提升索引层数的链表。最下面一…

如何使用 PHP 操作亚马逊 S3 对象云存储

以下是使用PHP与亚马逊S3对象云存储&#xff08;也有其他支持S3协议的云存储服务&#xff0c;原理类似&#xff09;进行交互的常见文档接口使用示例&#xff0c;涵盖了基本的操作如上传文件、下载文件、删除文件、列举文件等内容。 ### 前提条件 1. 首先&#xff0c;你需要获取…

APP推荐:全新TV端来了,8K原画电视版

▌ 软件介绍 B站都不陌生吧&#xff0c;一个能追番、学习、娱乐的多元平台&#xff0c;之前也分享过几款第三方TV端&#xff0c;其中的BV最近更新了全新版本。 使用了全新的UI界面&#xff0c;由之前的顶部菜单栏改成了侧边布局&#xff0c;已解锁限制&…

Pcl联合Qt显示点云

基于vs2022 勾选opengl&#xff0c;openglwidgets&#xff0c;并将widget控件提示为QVTKOpenGLNativeWidget Qt_Pcls.h #pragma once #include <QtWidgets/QMainWindow> #include "ui_Qt_Pcls.h" #include <vtkGenericOpenGLRenderWindow.h> #include &…

pip install transformers教程

直接pip install transformers会报错&#xff0c;报错内容如下&#xff1a; Collecting safetensors>0.3.1 (from transformers)Using cached safetensors-0.5.2.tar.gz (66 kB)Installing build dependencies ... doneGetting requirements to build wheel ... donePrepar…

【数据结构】基础知识

目录 1.1 什么是数据结构 1.2数据 1.3 逻辑结构 1.4 存储结构 1.4.1 顺序存储 1.4.2 链式存储 1.4.3 索引存储 1.4.4 散列存储 1.5 操作 1.1 什么是数据结构 数据的逻辑结构以及存储操作 数据结构没有那么复杂&#xff0c;它就教会你一件事&#xff1a;如何更有效的…

【Rust】变量与可变性

目录 思维导图 1. 变量与可变性 1.1 不可变性 1.2 可变性 2. 常量 2.1 定义与特性 3. 变量遮蔽&#xff08;shadowing) 3.1 影子机制 3.2 遮蔽与可变性的区别 4.示例 4.1 变量和可变性示例 4.2 可变变量示例&#xff1a; 4.3 常量示例&#xff1a; 4.4 遮蔽示例&a…

第27章 汇编语言--- 设备驱动开发基础

汇编语言是低级编程语言的一种&#xff0c;它与特定的计算机架构紧密相关。在设备驱动开发中&#xff0c;汇编语言有时用于编写性能关键的部分或直接操作硬件&#xff0c;因为它是接近机器语言的代码&#xff0c;可以提供对硬件寄存器和指令集的直接访问。 要展开源代码详细叙…

Mycat读写分离搭建及配置超详细!!!

目录 一、Mycat产生背景二、Mycat介绍三、Mycat安装四、Mycat搭建读写分离1、 搭建MySQL数据库主从复制2、 基于mysql主从复制搭建MyCat读写分离 五、Mycat启动常见错误处理1、Caused by: io.mycat.config.util.ConfigException: SelfCheck### schema TESTDB refered by user u…

【6】Word:海名公司文秘❗

目录 题目 List.docx Word.docx List.docx和Word.docx 题目 List.docx 选中1/4全角空格复制→选中全部文本→开始→替换&#xff1a;粘贴将1/4全角空格 替换成 空格选中全部文本→插入→表格→将文本转化成表格→勾选和布局→自动调整→勾选 选中第一列&#xff0c;单机右键…

【Rust】引用与借用

目录 思维导图 1. 引用与借用的基本概念 1.1. 引用示例 2. 借用的规则 2.1. 可变借用示例 2.2. 借用的限制 3. 引用的生命周期 思维导图 1. 引用与借用的基本概念 引用的定义&#xff1a;引用是一种指向数据的指针&#xff0c;但与裸指针不同&#xff0c;Rust的引用在编…

贪心算法详细讲解(沉淀中)

文章目录 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09;经典例题1.1.1 找零问题1.1.2最小路径和1.1.3 背包问题 2.贪心算法的特点2.1 证明例1 3.学习贪心的方向心得体会 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09; 贪心策略&a…

【专题】2025年节日营销趋势洞察报告汇总PDF洞察(附原数据表)

原文链接&#xff1a; https://tecdat.cn/?p38813 在当今复杂多变且竞争激烈的消费市场环境下&#xff0c;节日营销已成为企业获取市场份额、提升品牌影响力的关键战略时机。我们深知深入洞察节日营销趋势对于企业决策的重要性。 本报告汇总基于对 2024 年多个关键消费节点及…

51c自动驾驶~合集46

我自己的原文哦~ https://blog.51cto.com/whaosoft/13050104 #世界模型会是L3自动驾驶的唯一解吗 三维空间占有率&#xff08;3D Occupancy&#xff09;预测的目的是预测三维空间中的每个体素是否被占有&#xff0c;如果被占有&#xff0c;则对应的体素将被标记。3D Semant…