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中的工厂模式主要是用来将有大量共同接口的类实例化.工厂模式可以动态的决定将哪一个类实例化,不必事先知道要实例化哪个类,将类的实例化的主动权交给工厂而不是类本身.我们常见的 ...
随机推荐
- 第二章:视图层 - 9:动态生成CSV文件
CSV (Comma Separated Values),以纯文本形式存储数字和文本数据的存储方式.纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样的数据.CSV文件由任意数目的记录组成,记 ...
- Gitlab备份以及恢复
1.迁移准备工作和思路 从a服务器迁移到b服务器,由于Gitlab自身的兼容性问题,高版本的Gitlab无法恢复低版本备份的数据,需要注意在b服务器部署和a服务器一样版本的gitlab,部署好环境后开 ...
- vue基础之MV*和它们之间的不同
vue中的设计思想 vue中的设计思想主要是MV*模式,由最早的MVC(model-view-controller)框架,到后面的MVP(model-view-presenter),甚至到最后的MVV ...
- SQL语句——为什么分组函数(多行处理函数)不能用在where语句之后?
在SQL语句中,常见的分组查询函数为: sum()求和 avg()求平均值 min()求最小值 max()求最大值 count()求数目 在分组函数中有几个重要的特征: 1.分组函数进行时自动忽略nu ...
- Codeforces Round #442 (Div. 2) B. Nikita and string
题意:求最长可以分a b a为三部分子串,a b a可以为空 思路在代码里 1 #include<cstdio> 2 #include<iostream> 3 #include ...
- Springboot 之 Filter 实现超大响应 JSON 数据压缩
简介 项目中,请求时发送超大 json 数据外:响应时也有可能返回超大 json数据.上一篇实现了请求数据的 gzip 压缩.本篇通过 filter 实现对响应 json 数据的压缩. 先了解一下以下 ...
- Linux基础_2_bash功能
查看当前shell:echo $SHELL 查看可用shell:cat /etc/shells 命令行编辑 光标跳到行首:Ctrl+a 光标跳到行尾:Ctrl+e 以单词为单位快速跳转光标:Ctr ...
- java 新特性之 Stream API
强大的 Stream API 一.Stream API 的概述 Stream到底是什么呢? 是数据渠道,用于操作数据源(集合.数组等)所生成的元素序列. "集合讲的是数据,Stream讲的是 ...
- 创建外部表步骤及解决ORA-29913:执行ODCIETTABLEOPEN调出时出错
创建外部表步骤 建立目录对象(用sys用户创建.授权) 外部表所在路径一定要写对!!! create directory ext_data as 'D:\ORACLE'; grant read,wri ...
- 【单元测试】Junit 4(四)--Junit4参数化
1.0 前言 JUnit 4引入了一项名为参数化测试的新功能.参数化测试允许开发人员使用不同的值反复运行相同的测试. 1.1 参数化设置 这里我们直接上例子吧. 题目: 输入小写的字符串.如字 ...