Java工厂模式的最佳实践?
"Simplicity is prerequisite for reliability." - Edsger Dijkstra
“简单是可靠的前提条件。” —— 艾兹格·迪杰斯特拉
0x00 大纲
0x01 前言
最近在重温设计模式(in Java)的相关知识,然后在工厂模式的实现上面进行了一些较深入的探究,有了一些以前不曾注意到的发现,遂将其整理成文,以作后用。
工厂模式是典型的创建型模式,相比于创建简单对象的小作坊(new一个对象),它可以将复杂的构造逻辑进行封装,并对外暴露相对简单的接口方法,从而简化对象的创建流程。并在一定程度上提供平替模块而不用改变代码结构的灵活特性。
在许多书籍和文献里喜欢将工厂模式划分为简单工厂模式和抽象工厂模式,但是我个人认为它们或许并没有如此明确的界限——至少在OOP里面。继承的存在使得我们的“工厂”和”产品“都可以是多态的,我认为理解这一点尤为重要。工厂模式只是一种对复杂构造流程的封装,至于抽象程度高还是低并不影响它的本质。
通过代码来展示工厂模式的文章已经很多了,但我认为它很无聊且脱离实际,有点通过答案来倒推过程的味道。我将用一个夸张的故事来说明工厂模式的局限,以及需要注意的地方,提醒自己在今后的工作中不要犯这样的错误——当我得意忘形,以为自己很聪明的时候。
0x02 理想的工厂模型
通常来说,只有明确了我们的“产品”是什么,才能知道我们需要怎么样的“工厂”。我们假定最初的产品是一个MP3播放器,它的构造很复杂,因此我们引入了一个工厂类用来创建它的实例。为了应对未来可能的修改,我们对解码器和解码器工厂做了接口的抽象,看起来像这样:

到目前为止,它都符合我们的设计预期,运作良好。我们甚至有足够的信心应对未来可能的(想像中的)需求变更:“随着业务的发展,只支持MP3格式的播放器看起来已经太寒酸了,于是乎引入了其它的播放格式。得益于我们之前的设计,不用改动原来的代码,只需要增加一组实现就能实现新增的需求,so easy.”

然而,现实总是打脸的,经过产品的深入调研,决定将播放器业务扩展到视频领域,对没错,就先支持个H.264编码的视频流吧,好像同行竞品都在用呢。于是,开发人员不得不重新考量原来的设计。于是经过若干个996,开发组调整了原来的设计,并完成了下面的系统:

开发人员顶着黑眼圈,面带满意微笑地在最后期限的前一天晚上提交了代码——这下无论它增加音频格式和视频格式,我们都可以灵活应对了,嘿嘿嘿!负责架构的小锅拍着胸脯向各位开发成员如是说道。并在PPT上附上了下一阶段的(想像中的)技术方向:

新入职的初级开发小蔡似乎觉得有什么地方不太对劲,欲言又止。但下一秒又安慰自己:肯定是我自己经验不足,理解还不到位,这个设计应该没有问题!
0x03 道高一尺魔高一丈
随着一阵聊天工具此起彼伏的响声,产品又紧急召集众人开会了。”来活了各位,我们的播放器面对同行毫无优势,经过我们的研究,决定在原有的播放基础上,增加转换输出的功能!速度要快,质量要稳!对了,最好能多支持几种格式,最好市面上找得到的格式都支持一下。“各位开发脸色铁青,尤其是架构师小锅的脸色黑得最为纯粹。
由于研发周期短,项目组来不及细细思考和重新设计,只能在原有项目基础上增加相关的模块来应对新的需求。半小时讨论,半小时敲定。大家一致决定,不如就沿用原来工厂模式的设计,反正我们已经有前面的经验,应该不会有什么大问题,于是新的设计诞生了:

为了维持项目原有的结构设计,开发人员在编码阶段似乎显得有点不堪重负,经过两周紧锣密鼓的开发,项目不出所料地延期了。
年轻的被寄予厚望的架构师小锅在复盘会议上失去了往昔眼中的高光。
0x03 何谓最佳实践
以至于多年以后,在公司新来的架构师小程向大家讲述工厂模式的巧妙应用的那一刻。
不再年轻的小锅又回想起三月里那个温暖的下午。注:就是去背锅的那个下午。
小锅起身,先是肯定了小程扎实的基本功和流畅的表达,随后又把当年的往事向大家娓娓道来,边板书边讲,尽最大可能向大家讲述了当年事情的来龙去脉,并作出总结:
- 切勿盲目自信,陷入教条的陷阱
- 你可以预见变更,但永远不能预测需求
- 过早的优化是万恶之源
众人陷入沉默,随后年轻的小程率先打破僵局,向小锅问道:”那么,最后,问题是怎么解决的呢?“
小锅微微一笑,先是没有说话,随后转过身去疯狂画起图来,毕了潇洒转身将手背到身后,说:”从哪里跌倒就从哪里站起来。“

0x04 小结
为了更好的说明工厂模式能解决什么问题,不能解决什么问题,以上故事纯属虚构,饱含夸张的成分,如有雷同,请勿对号入座。
回到最初的起点,只有明确了我们的“产品”是什么,才能知道我们需要怎么样的“工厂”。 不必着急引入模式,先让产品飞一会儿。在不稳定的维度上引入工厂模式是没有意义的,因为异变需求无法被初始抽象完全界定,错误的抽象还不如不抽象。
Java工厂模式的最佳实践?的更多相关文章
- java工厂模式
(1)概念大白话:java工厂模式就是客户端(main函数)要创建对象觉得麻烦就让另外一个叫工厂的类帮它创建,然后自己每次要创建对象就叫工厂帮它弄,举个例子,在没有工厂这个"手下" ...
- paip.java gui swt/jface 最佳实践
paip.java gui swt/jface 最佳实践 1. 工具:Eclipse +jigloo4 1 2. 安装插件: 1 1. IMPORT swt lib 2 2. 新建立窗体 2 3. 运 ...
- paip.提升性能--多核编程中的java .net php c++最佳实践 v2.0 cah
paip.提升性能--多核编程中的java .net php c++最佳实践 v2.0 cah 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax ...
- atitit.Atitit. Gui控件and面板-----服务端控件 java struts的实现最佳实践
atitit.Atitit. Gui控件and面板-----服务端控件 java struts的实现最佳实践 1. 服务器控件的类别 1 1.1. 数据控件:该类控件可细分为两种类型:数据源控件和数 ...
- Java工厂模式解耦 —— 理解Spring IOC
Java工厂模式解耦 -- 理解Spring IOC 最近看到一个很好的思想来理解Spring IOC,故记录下来. 资源获取方式 主动式:(要什么资源都自己创建) 被动式:(资源的获取不是我们创建, ...
- Java学习笔记——Java工厂模式之简单工厂
package com.app; import java.util.Date; /* * 工厂模式:简单工厂.工厂方法.抽象工厂 * * */ public class Test0718_Factor ...
- [Java Performance] 数据库性能最佳实践 - JPA和读写优化
数据库性能最佳实践 当应用须要连接数据库时.那么应用的性能就可能收到数据库性能的影响. 比方当数据库的I/O能力存在限制,或者因缺失了索引而导致运行的SQL语句须要对整张表进行遍历.对于这些问题.只相 ...
- JAVA - 工厂模式
1. 简单工厂违背OCP(Open Close Principle)原则 , 即对增加开放,对修改关闭.如果要符合OCP原则,要针对接口编程. //简单工厂模式,违反了OCP原则 public cla ...
- Java 工厂模式(一)— 抽象工厂(Abstract Factory)模式
一.抽象工厂模式介绍: 1.什么是抽象工厂模式: 抽象工厂模式是所有形态的工厂模式中最为抽象和最具有一般性的一种形态,抽象工厂模式向客户端提供一个接口,使得客户端在不知道具体产品的情类型的情况下,创建 ...
- Java 工厂模式(一)— 简单工厂模式
一.什么是工厂模式: Java中的工厂模式主要是用来将有大量共同接口的类实例化.工厂模式可以动态的决定将哪一个类实例化,不必事先知道要实例化哪个类,将类的实例化的主动权交给工厂而不是类本身.我们常见的 ...
随机推荐
- 小白入行安全圈内必须知道的top10
OWASP Top10 前言 每年的Top10都在更新,但是一般不会有太大的改变,这里说明的是 2021年的Top10排行榜. A01:访问控制失效(Broken Access Control) 攻击 ...
- 工业互联网领域的企业,都已经接入了ERP或者MES系统了吗?
肯定不是得啊!之前的两化,后来的企业上云,到当下的智能制造.数字化转型,不都是想把制造业(也就是你说的工业互联网企业)往这个方向推么,ERP和MES是企业数字化的一部分,但不是全部,当然有的企业(小工 ...
- HTML5中新增实用的标签
1:progress 进度条 <h3>progress</h3> <progress value="75" max="100"& ...
- Docker 部署 Kibana
Docker 部署 Kibana 本篇主要介绍 使用 Docker 部署 kibana 用于操作 Elasticsearch 使用. 1. 前置准备 1.1 Elasticsearch 准备 可以先准 ...
- VMware vSphere 8.0 正式版下载
请访问原文链接:https://sysin.org/blog/vmware-vsphere-8/,查看最新版.原创作品,转载请保留出处. 作者主页:www.sysin.org vSphere 8.0 ...
- 『现学现忘』Git后悔药 — 32、revert撤销(一)
目录 1.Git的三种后悔药 2.revert命令原理 3.revert命令的使用 (1)移除某次提交的修改 (2)revert命令说明 1.Git的三种后悔药 在Git中后悔药有三种:amend.r ...
- 微信小程序js-时间转换函数使用
最近在做云开发博客小程序 采集微信发布的信息放入数据库会有createTime因此发现了不一样的地方 云函数可以直接使用 但是放到引导全局的app.js文件却是找不到该方法-->dateform ...
- 『现学现忘』Git基础 — 37、标签tag(二)
目录 5.共享标签 6.删除标签 7.修改标签指定提交的代码 8.标签在.git目录中的位置 9.本文中所使用到的命令 提示:接上一篇文章内容. 5.共享标签 默认情况下,git push 命令并不会 ...
- 27.路由器Routers
像一些reils这样的web框架提供自动生成urls的功能,但是Django没有 rest framework为django添加了这一功能,以一种简单.快速.一致的方式 routers必须配合view ...
- NAS数据存储之NFS搭建和使用
NFS是主流异构平台的共享文件系统之一,能够支持在不同类型的系统之间通过网络进行文件共享,允许一个系统在网络上与他人共享目录和文件.NFS传输协议用于服务器和客户机之间的文件访问和共享通信,从而使客户 ...