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中的工厂模式主要是用来将有大量共同接口的类实例化.工厂模式可以动态的决定将哪一个类实例化,不必事先知道要实例化哪个类,将类的实例化的主动权交给工厂而不是类本身.我们常见的 ...
随机推荐
- Typora如何配置gitee图床
转载自:https://mp.weixin.qq.com/s/5dPLbr2vFgL18XKL1Y05Og 要求: 1.Typora需要升级到最新版 2.需要安装nodejs PicGo软件下载地址: ...
- 【原创】推流录屏软件OBS使用教程--录屏
之前有录屏需要,写了一篇关于ffmpeg录屏的文章,反响还不错,但是直接用ffmpeg门槛有些高,今天写一篇图形界面的录屏推流工具OBS的使用教程.这次先写OBS的录屏教程 下载安装 点击 OBS官网 ...
- Spring让人眼前一亮的11个小技巧
前言 我们一说到spring,可能第一个想到的是 IOC(控制反转) 和 AOP(面向切面编程). 没错,它们是spring的基石,得益于它们的优秀设计,使得spring能够从众多优秀框架中脱颖而出. ...
- Codeforces Round #709 Div2
就ac了一题.QAQ掉分了我好难过. A题要画图推出来公式. B不会,现在没看到好懂得题解. C题,思路错了,给一些数,每天只能选其中一些,每个数不能被选超过k次,应该先将每天只能选一个得这个数先选上 ...
- DDD-领域驱动(四)-使用IMediator 实现领域事件
领域事件是指:一个领域中出触发的 集成事件是指:多个微服务之前产生的事件 核心对象 IMediator INotification INotificationHandler 引入:IMediator ...
- 5.ElasticSearch系列之文档的基本操作
1. 文档写入 # create document. 自动生成 _id POST users/_doc { "user" : "shenjian", " ...
- Linux基础_5_文件管理
创建 touch 文件名 #创建文件 stat 文件名 #查看文件属性 touch -am 文件名 #更改文件的访问时间及修改时间 删除 rm -rf s/* #递归强制删除s目录下的所有内容(包括文 ...
- 【Chrome浏览器】关闭触摸板双指滑动进行前进后退的功能
痛点 Chrome浏览器使用过程中,当前页面经常会莫名其妙地退回到上一个浏览的页面. 当时真是一脸懵B(心里一万头草泥马呼啸而过~)!以为活见鬼了! 后来才发现浏览器左边,有一个幽灵般的淡蓝色箭头的出 ...
- Redis—问题(1)
写在前面 Redis 是一种 NoSQL 数据库,包含多种数据结构.支持网络.基于内存.可选持久性的键值对存储数据库,在我们的日常开发中会经常使用 Redis 来解决许多问题,比如排行榜.消息队列系统 ...
- java中GC的日志认识详解
不同的垃圾回收器 他们的日志都是完成不一样的,看懂日志是解决和发现问题的重中之重. Parallel Scavenge + Parallel Old 日志 启动参数 -XX:+UseParallelG ...