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,一经查实,立即删除!

相关文章

深入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;的基本操作。 …

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

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

【数据结构】基础知识

目录 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…

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…

Linux-----线程操作(创建)

目录 创建线程 示例&#xff1a; 创建线程 #include <pthread.h>/*** 创建一个新线程* * pthread_t *thread: 指向线程标识符的指针,线程创建成功时,用于存储新创建线程的线程标识符* const pthread_attr_t *attr: pthead_attr_t结构体,这个参数可以用来设置线程的属性…

华三S6520交换机配置console和ssh

目录 一、实验目的 二、实验设备 三、实验拓扑图 四、实验步骤 1、console用户名和密码 2、ssh用户名和密码 3.配置系统时间 一、实验目的 实现对华三 S6520 交换机的 console 本地登录和 ssh 远程登录配置,确保能够通过 console 线在本地进行管理,并使用 SSH 协议进…

Vue3组件设计模式:高可复用性组件开发实战

Vue3组件设计模式:高可复用性组件开发实战 一、前言 在Vue3中&#xff0c;组件设计和开发是非常重要的&#xff0c;它直接影响到应用的可维护性和可复用性。本文将介绍如何利用Vue3组件设计模式来开发高可复用性的组件&#xff0c;让你的组件更加灵活和易于维护。 二、单一职责…

1月13日学习

[HITCON 2017]SSRFme 直接给了源代码&#xff0c;题目名称还是ssrf&#xff0c;那么该题大概率就是SSRF的漏洞&#xff0c;进行代码审计。 <?php// 检查是否存在 HTTP_X_FORWARDED_FOR 头&#xff0c;如果存在&#xff0c;则将其拆分为数组&#xff0c;并将第一个 IP 地址…

linux RT-Preempt spin lock实现

一、spin_lock概述 Spinlock是linux内核中常用的一种互斥锁机制&#xff0c;和mutex不同&#xff0c;当无法持锁进入临界区的时候&#xff0c;当前执行线索不会阻塞&#xff0c;而是不断的自旋等待该锁释放。正因为如此&#xff0c;自旋锁也是可以用在中断上下文的。也正是因为…

设计模式-工厂模式/抽象工厂模式

工厂模式 定义 定义一个创建对象的接口&#xff0c;让子类决定实列化哪一个类&#xff0c;工厂模式使一个类的实例化延迟到其子类&#xff1b; 工厂方法模式是简单工厂模式的延伸。在工厂方法模式中&#xff0c;核心工厂类不在负责产品的创建&#xff0c;而是将具体的创建工作…