创建者模式:工厂方式模式
2025-09-23 12:07 tlnshuju 阅读(0) 评论(0) 收藏 举报生动讲解工厂方法模式
想象你要开一家"日志打印店":
1. 客户只需要说:"我要打印日志"
2. 不用关心是用打印机(文件日志)还是刻石碑(数据库日志)
3. 你根据订单类型自动选择对应的生产工具
这就是工厂方法模式的核心:**让子类决定创建什么对象**,客户端只需面向接口编程。
---
### 一、工厂方法模式四大核心组件
#### 1. 抽象产品(Logger接口)
```java
// 相当于"印刷品标准"
public interface Logger {void writeLog(); // 所有日志都必须支持打印功能
}
```
#### 2. ️ 具体产品(FileLogger/DataBaseLogger)
```java
// 文件日志 - 相当于"纸质印刷"
public class FileLogger implements Logger {public void writeLog() {System.out.println("正在使用文件日志记录器记录日志");}
}
// 数据库日志 - 相当于"石碑雕刻"
public class DataBaseLogger implements Logger {public void writeLog() {System.out.println("正在使用数据库日志记录器记录日志");}
}
```
#### 3. 抽象工厂(LoggerFactory接口)
```java
// 印刷厂生产标准
public interface LoggerFactory {Logger createLogger(); // 所有工厂必须能生产日志产品
}
```
#### 4. 具体工厂(FileLoggerFactory/DataBaseLoggerFactory)
```java
// 文件日志工厂 - 专门生产纸质印刷品
public class FileLoggerFactory implements LoggerFactory {public Logger createLogger(){System.out.println("️ 启动文件印刷流水线");return new FileLogger();}
}
// 数据库日志工厂 - 专门生产石碑雕刻
public class DataBaseLoggerFactory implements LoggerFactory {public Logger createLogger() {System.out.println("⛏️ 启动石碑雕刻工坊");return new DataBaseLogger();}
}
```
---
### 二、工作流程(客户下单场景)
```java
public class Client {public static void main(String[] args) {// 1. 获取工厂配置(客户选择印刷方式)LoggerFactory factory = XMLUtil.getBean();// 2. 创建日志产品(工厂生产)Logger logger = factory.createLogger();// 3. 使用产品(客户收货使用)logger.writeLog();}
}
```
#### 配置文件(订单需求单)
```xml创建者模式.工厂方法模式.具体工厂.FileLoggerFactory
```
#### 配置解析器(订单处理中心)
```java
public class XMLUtil {public static LoggerFactory getBean() {// 1. 读取配置文件(接收订单)// 2. 解析XML获取类名(理解需求)String className = "创建者模式.工厂方法模式.具体工厂.FileLoggerFactory";// 3. 反射创建工厂(分配对应工厂)Class clazz = Class.forName(className);return (LoggerFactory) clazz.newInstance();}
}
```
---
### 三、实际开发应用场景
#### 场景1:支付网关切换
```java
// 抽象产品
interface Payment {void pay(double amount);
}
// 具体产品
class Alipay implements Payment { /* 支付宝实现 */ }
class WechatPay implements Payment { /* 微信支付实现 */ }
// 抽象工厂
interface PaymentFactory {Payment create();
}
// 客户端
public class PaymentClient {public void processOrder(String paymentType) {PaymentFactory factory = PaymentConfig.getFactory(paymentType);Payment payment = factory.create();payment.pay(100.00);}
}
```
#### 场景2:跨数据库支持
```java
// 抽象产品
interface DatabaseConnection {void connect();
}
// 具体产品
class MySQLConnection implements DatabaseConnection { /* ... */ }
class OracleConnection implements DatabaseConnection { /* ... */ }
// 配置文件切换MySQLOracle -->
```
#### 场景3:多格式导出功能
```java
class ExportFactory {public static Exporter getExporter(String format) {switch(format) {case "PDF": return new PDFExporterFactory();case "EXCEL": return new ExcelExporterFactory();default: throw new IllegalArgumentException("不支持的格式");}}
}
```
---
### 四、六大核心优势
1. **解耦王者**:客户端只依赖抽象(Logger),不依赖具体实现```mermaidgraph LRClient-->|依赖|LoggerClient-->|依赖|LoggerFactoryLoggerFactory-->|生产|Logger```
2. **开闭原则典范**:新增产品只需扩展,无需修改已有代码```java// 新增云日志产品class CloudLogger implements Logger { /* ... */ }class CloudLoggerFactory implements LoggerFactory { /* ... */ }```
3. **可配置性**:通过配置文件实现零代码修改切换实现```xmlcom.example.CloudLoggerFactory```
4. **职责清晰**:每个工厂只负责创建一种产品
5. **可测试性**:轻松Mock工厂进行单元测试
6. **可扩展性**:天然支持产品族扩展(结合抽象工厂模式)
---
### 五、五大避坑指南
1. **避免过度设计**✅ 简单场景用简单工厂:```javaclass LoggerFactory {public static Logger create(String type) {switch(type) {case "FILE": return new FileLogger();case "DB": return new DataBaseLogger();}}}```❌ 不要为只有1-2种实现的场景上完整工厂模式
2. **防止循环依赖**工厂不应依赖具体产品,应依赖抽象产品```java// 正确示范 ✅class FileLoggerFactory implements LoggerFactory {public Logger createLogger() { // 返回接口return new FileLogger();}}```
3. **性能考量**频繁创建对象时考虑对象池:```javaclass DatabaseLoggerFactory {private static Queue pool = new ConcurrentLinkedQueue<>();public Logger createLogger() {Logger logger = pool.poll();if(logger == null) {logger = new DatabaseLogger();}return logger;}}```
4. **异常处理**工厂方法应明确处理创建失败:```javapublic Logger createLogger() throws CreateException {try {return new DatabaseLogger();} catch (DBConnectionException e) {throw new CreateException("数据库连接失败", e);}}```
5. **避免反射滥用**配置化创建时要防御非法类:```java// XMLUtil改进if(!LoggerFactory.class.isAssignableFrom(clazz)) {throw new IllegalArgumentException("非法工厂类");}```
---
### 六、三种演进形态
| 模式类型 | 适用场景 | 示例 |
|----------------|-----------------------------------|--------------------------|
| 简单工厂 | 产品类型固定且较少 | `LoggerFactory.create(type)` |
| **工厂方法** | 需要灵活扩展产品 | 本文示例 |
| 抽象工厂 | 创建相关产品族(如不同主题UI组件)| `ThemeFactory.createButton()/createMenu()` |
---
### 七、最佳实践总结
1. **识别变化点**:将易变的创建逻辑封装进工厂
2. **面向接口编程**:客户端代码只与抽象产品/工厂交互
3. **配置化创建**:对频繁切换的实现使用配置文件+反射
4. **工厂命名规范**:使用`XXXFactory`统一后缀
5. **结合单例模式**:工厂本身通常实现为单例
```java
// 典型应用框架
DatabaseConnection conn = ConnectionFactory.getFactory(DatabaseType.MYSQL).createConnection();
```
> **黄金法则**:
> 当你的代码中出现`new`关键字时,问问自己:
> "这个对象的创建逻辑未来会变化吗?"
> 如果答案是肯定的,就该请出工厂方法模式了!
工厂方法就像制造业的"标准化生产线",让产品制造与使用分离。正确使用能让你的代码像乐高积木一样灵活组装,应对各种需求变化!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/912491.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!相关文章
承兑 背书 贴现区别
承兑 背书 贴现区别 承兑、背书与贴现是票据业务中的三个重要概念,它们在票据的流通和融资过程中各自扮演着不同的角色。一、承兑承兑是指汇票付款人承诺在汇票到期日支付汇票金额的票据行为。根据《中华人民共和国票…
义乌制作网站建设网站公
第一范式:
属性不可分割:每个属性都是不可分割的原子项(实体的属性就是表中的列) 在上表中contact应该分为phone和adress两列 第二范式:
在满足第一范式的情况下,表中不存在部分依赖,非主键列…
怎样在设计网站做图赚钱省建设厅网站梁作庆
文章目录1 概述2 总体框架3. 计算Onset Strength Envelope4 计算全局的Tempo5 基于动态规划计算beats6 参考文献1 概述
有背景音乐的短视频拼接时,如果两个视频的拼接点刚好在背景音乐的某个节拍点上,那么合成的视频看起来,听起来࿰…
淄博网站建设兼职建筑工程网名大全霸气
前言
如今进行入自媒体行业的人越来越多,短视频也逐渐成为了主流,但好多时候是想如何把视频里面的语音转成文字,比如,录制会议视频后,做会议纪要;比如,网课教程视频,想要做笔记&…
html做网站自适应宽度网络推广方式方法
在互联网的浩瀚星空里,火星文和变异字体如同璀璨的繁星,照亮了网络世界的角落。它们以独特的创意和视觉冲击力,吸引着无数网友的目光。让我们一起走进这个充满创意和想象力的世界,感受火星文和变异字体的无限魅力。
火星文生成器…
wordpress网站弹窗插件做网站公司南京
为何诞生 在说transformer是什么,有什么优势之类的之前,先谈一谈它因何而诞生。transformer诞生最重要的原因是早先的语言模型,比如RNN,由于其本身的训练机制导致其并行度不高,特别是遇到一些长句子的情况下。其次&…
织梦高端大气网站模板外卖网站建设的策划书
打卡记录 需要添加的硬币的最小数量(归纳法)
链接 按着已经加入的数,以此偏移对应距离,从而得到新的连续数,若是出现断层则计入最小次数中,再以此偏移对应距离。
class Solution:def minimumAddedCoins(s…
个人网站当企业网站用互联网保险平台有哪些
hello-algo 是一个为帮助编程爱好者系统地学习数据结构和算法的开源项目。这款项目通过多种创新的方式,为学习者提供了一个直观、互动的学习平台。 本文将详细的介绍如何利用 Docker 在本地安装部署 hello-algo,并结合路由侠内网穿透实现外网访问本地部署…
画江湖网站开发文档淄博 网站制作
文章目录一、安装虚拟机1. 新建虚拟机2. 稍后安装3. 选择linux版本4. 安装位置5. 处理器配置6. 内存配置7. 网络配置8. 创建新磁盘9. 设置磁盘大小10. 选择镜像,完成二、虚拟机配置2.1. 重新启动2.2. 选择语言2.3. 设置时区2.4. 选择安装模式2.5. 自定义分区2.6. 接…
洛谷题单指南-进阶数论-P3811 【模板】模意义下的乘法逆元
原题链接:https://www.luogu.com.cn/problem/P3811
题意解读:逆元的模版题。
解题思路:
1、同余和模运算
同余定义:若整数 a 和 b 除以 m 的余数相同,称 a 与 b 模 m 同余,记为 a ≡ b (mod m)
模运算符号:a mo…
北京交通管制信息网站wordpress 获取页面标题
题目
输入一个字符串,打印该字符中字符的所有排列。
例如,输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串有abc、acb、bac、bca、cab、cba
分析
把一个字符串看成由两部分组成:第一部分是它的第一个字符&#…
山西省建设局官方网站中企动力值不值得入职
19-20年VIO 梳理 1. 开源代码介绍: DSM2. FMD Stereo SLAM:融合MVG和直接方法,实现准确,快速的双目SLAM3. 基于VINS-Mono开发的SPVIS4. 改进:一种基于光流的动态环境移动机器人定位方案5. PVIO:基于先验平面约束的高效…
消防设备网站建设怎么找做网站的
事务的简单配置及使用 配置事务管理器声明队列生产者代码测试 RabbitMQ是基于AMQP协议实现的,该协议实现了事务机制,因此RabbitMQ也支持事务机制. SpringAMQP也提供了对事务相关的操作.RabbitMQ事务允许开发者确保消息的发送和接收是原子性的,…
贵阳市观山湖区建设局网站深圳系统开发高端网站建设
1. probability space 概率空间
1.1 概率基础 1.2 概率空间 2. Filtration
filtration在钱敏平老师和龚光鲁老师的《随机过程论》中直接称其为非降的KaTeX parse error: Undefined control sequence: \sigmma at position 1: \̲s̲i̲g̲m̲m̲a̲代数族。如图。 一般叫σ\…
科技公司网站设计欣赏从零开始学习网络营销
目录 0. 前言1. Ubuntu24.04的安装2. Ubuntu24.04的配置2.1 基本配置2.2 开发环境配置 0. 前言
我去年在做一个项目的时候需要用到ros,ros需要运行在Ubuntu系统上。但我的笔记本电脑配置不是很好,采用虚拟机运行的想法随之被否决,决定采用安…
中山网站设计与建设全球新冠最新数据报告
SpringBoot-AOP
AOP基础
学习完spring的事务管理之后,接下来我们进入到AOP的学习。 AOP也是spring框架的第二大核心,我们先来学习AOP的基础。
在AOP基础这个阶段,我们首先介绍一下什么是AOP,再通过一个快速入门程序,…
四川成都网站优化oppo网站建设
1、WPF 4 DataGrid 控件(基本功能篇) 基本使用,绑定数据展示 2、WPF 4 DataGrid 控件(自定义样式篇) 定义行,列,头,单元格等样式 3、WPF 4 DataGrid 控件(进阶篇一&#…
电子书城网站开发项目概况洛阳建站哪家好
1049. 数列的片段和(20) 时间限制200 ms内存限制65536 kB代码长度限制8000 B判题程序Standard作者CAO, Peng给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段。例如,给定数列{0.1, 0.2, 0.3, 0.4},我们有(0.1) (0.1…
如何通过做网站挣钱天猫开店流程及费用2022
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 进度条是一个比较常见的控件。如果某个操作需要很长的时间才能完成,那么这个时候最好有一个进度条提示,这样比较容易平复一…
Interlocked.Increment学习
Interlocked.Increment 是 .NET 中的一个原子操作方法,用于线程安全地将一个整型变量递增 1。Interlocked.Increment 是线程安全地递增整数的标准方式,适用于高并发计数场景。定义:
public static int Increment(re…