"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工厂模式的最佳实践?的更多相关文章

  1. java工厂模式

    (1)概念大白话:java工厂模式就是客户端(main函数)要创建对象觉得麻烦就让另外一个叫工厂的类帮它创建,然后自己每次要创建对象就叫工厂帮它弄,举个例子,在没有工厂这个"手下" ...

  2. paip.java gui swt/jface 最佳实践

    paip.java gui swt/jface 最佳实践 1. 工具:Eclipse +jigloo4 1 2. 安装插件: 1 1. IMPORT swt lib 2 2. 新建立窗体 2 3. 运 ...

  3. paip.提升性能--多核编程中的java .net php c++最佳实践 v2.0 cah

    paip.提升性能--多核编程中的java .net php c++最佳实践  v2.0 cah 作者Attilax  艾龙,  EMAIL:1466519819@qq.com  来源:attilax ...

  4. atitit.Atitit. Gui控件and面板-----服务端控件 java struts的实现最佳实践

    atitit.Atitit.  Gui控件and面板-----服务端控件 java struts的实现最佳实践 1. 服务器控件的类别 1 1.1. 数据控件:该类控件可细分为两种类型:数据源控件和数 ...

  5. Java工厂模式解耦 —— 理解Spring IOC

    Java工厂模式解耦 -- 理解Spring IOC 最近看到一个很好的思想来理解Spring IOC,故记录下来. 资源获取方式 主动式:(要什么资源都自己创建) 被动式:(资源的获取不是我们创建, ...

  6. Java学习笔记——Java工厂模式之简单工厂

    package com.app; import java.util.Date; /* * 工厂模式:简单工厂.工厂方法.抽象工厂 * * */ public class Test0718_Factor ...

  7. [Java Performance] 数据库性能最佳实践 - JPA和读写优化

    数据库性能最佳实践 当应用须要连接数据库时.那么应用的性能就可能收到数据库性能的影响. 比方当数据库的I/O能力存在限制,或者因缺失了索引而导致运行的SQL语句须要对整张表进行遍历.对于这些问题.只相 ...

  8. JAVA - 工厂模式

    1. 简单工厂违背OCP(Open Close Principle)原则 , 即对增加开放,对修改关闭.如果要符合OCP原则,要针对接口编程. //简单工厂模式,违反了OCP原则 public cla ...

  9. Java 工厂模式(一)— 抽象工厂(Abstract Factory)模式

    一.抽象工厂模式介绍: 1.什么是抽象工厂模式: 抽象工厂模式是所有形态的工厂模式中最为抽象和最具有一般性的一种形态,抽象工厂模式向客户端提供一个接口,使得客户端在不知道具体产品的情类型的情况下,创建 ...

  10. Java 工厂模式(一)— 简单工厂模式

    一.什么是工厂模式: Java中的工厂模式主要是用来将有大量共同接口的类实例化.工厂模式可以动态的决定将哪一个类实例化,不必事先知道要实例化哪个类,将类的实例化的主动权交给工厂而不是类本身.我们常见的 ...

随机推荐

  1. kvm安装windows使用virtio驱动下载地址

    https://dl.fedoraproject.org/pub/alt/virtio-win/latest/images/bin/deprecated-README 老版本下载地址:https:// ...

  2. 示例:Ingress通过互联网访问应用

    Ingress Ingress 是 Kubernetes 的一种 API 对象,将集群内部的 Service 通过 HTTP/HTTPS 方式暴露到集群外部,并通过规则定义 HTTP/HTTPS 的路 ...

  3. Visual Studio 2022 开发 STM32 单片机 - 环境搭建点亮LED灯

    安装VS2022社区版软件 选择基础的功能就好 安装VisualGDB软件(CSDN资源) 按照提示一步一步安装就好 VisualGDB激活软件(CSDN资源) 将如下软件放在VisualGDB的安装 ...

  4. 220722 T4 求和 /P4587 [FJOI2016]神秘数 (主席树)

    好久没打主席树了,都忘了怎么用了...... 假设我们选了一些数能构成[0,x]范围内的所有值,下一个要加的数是k(k<=x+1),那么可以取到[0,x+k]内的所有取值,所以有一种做法: 对于 ...

  5. 案例分享-https证书链不完整导致请求失败

    背景 话不多说,直接上堆栈 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX p ...

  6. PHP Phar反序列化学习

    PHP Phar反序列化学习 Phar Phar是PHP的压缩文档,是PHP中类似于JAR的一种打包文件.它可以把多个文件存放至同一个文件中,无需解压,PHP就可以进行访问并执行内部语句. 默认开启版 ...

  7. Docker | 使用dockerfile生成镜像,清理docker空间

    用dockerfile生成镜像并挂载数据卷 编写dockerfile文件 创建dockerfile01 文件 # 基础镜像 FROM centos VOLUME ["volume01&quo ...

  8. (数据科学学习手札144)使用管道操作符高效书写Python代码

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,一些比较熟悉pandas的读者 ...

  9. java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter 增样将jar包导入

    2021-9-30-17:28 遇到的一个bug.以前遇到过,这次又遇到.就离谱,结果还忘记怎样解决了.这捣鼓一下,那捣鼓一下,又给搞好了.为了记录这次bug,又试图还原bug. 1.解决办法file ...

  10. 一天五道Java面试题----第六天(1)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1.mybatis和hibernate的对比 2 .#{}和${}的区别 3 .mybatis插件运行原理及开发流程 4 ...