理解设计模式之工厂模式

本贴最后更新于 1892 天前,其中的信息可能已经事过景迁

什么是工厂模式?

  上一篇文章写了关于创建模式之一的单例模式,这篇依然是关于创建模式的,最常用的模式之一,工厂模式。那么到底什么是工厂模式?理解工厂模式的概念很容易,光看工厂两个字就知道了,就是用来生产东西的,工厂模式,可以理解为专门用于生产对象的类,这个类不做其他的,就是生产对象。那么为什么会出现这个模式?我们直接 new 一个对象不就好了吗?还这么麻烦要专门用一个类来干这个事,不是多此一举么?其实不然,工厂模式提倡了“面向接口”编程的思想,将具体对象的创建跟业务代码解耦,让业务不用关心对象是如何产生的,只需要调用业务对象的接口即可。你想想,如果是 new 一个对象,然后再初始化这个对象的一些属性,万一哪天对象发生了变化,增加了一个需要初始化的属性,岂不是所有 new 这个对象的地方都会改一遍?这明显违背了“开闭原则”。因此工厂模式的出现,正是解决对象创建跟业务代码紧耦合这个问题。

工厂模式分类

  工厂模式就是工厂模式,干嘛还要分类呢?初学者可能对这个问题比较疑惑。为啥要分一下类呢?因为工厂这个东西,会随着产品的复杂程度而变化,跟现实世界中的一样,一个简单的工厂流水线不可能生产出种类繁多又很复杂的产品,那么随着产品的变化,工厂的实现也会跟着变化。根据以往查看过的资料来看,工厂模式一共分为三类:简单工厂、工厂方法、抽象工厂。看了一下网上的资料,与以往的总结,简单描述一下自己对这三类工厂实现的理解(只讲原理,不贴代码)。
  简单工厂 Simple Factory
  简单工厂,为啥要叫简单工厂?因为简单。我这个工厂只生产一个种类的产品,不生产其他东西,那么这个工厂就是简单工厂。例如假如你开了一个面食厂,专门做包子,生产肉包、菜包和豆沙包(如果你想买馒头,不好意思,到隔壁老王的馒头店去)。结合 UML 类图理解一下:
png
  工厂方法 Factory Method
  上面是简单工厂,只能生产一些简单的东西,我就生产这类产品,还是拿面食厂举例,面食厂开张后,生意好了,吃得人越来越多,时间久了大家觉得一个师傅做出来的口味始终是一个味道(想想你们在公司食堂吃了一年的饭菜),这时候突然有人提议,要吃换个口味的包子,但是包子还是肉包、菜包和豆沙包,这个时候怎么办?那么就轮到工厂方法出马了,工厂方法模式生产的产品还是那几样,但是实现者却不一样,实现的产品也不一样,拿面食店举例,假如之前是请老干妈做的包子,那么现在又请了一个老干爹,做口味不一样的包子。结合 UML 类图理解一下:
png
  虽然都是肉包子,但是老干妈的肉包子跟老干爹的肉包子是不一样的口味,因此工厂方法,适合同款产品有多种不同实现的场景。最简单的应用场景如数据库驱动,数据库驱动标准接口是
java.sql.Driver,Driver 生产 java.sql.Connection 对象。实现 java.sql.Driver 接口的驱动程序有跟多,例如 MySQL 的驱动与 Oracle 的驱动,两者生产的 Connection 对象也分别是基于 MySQL 数据库的实现和 Oracle 数据库的实现,但是对于业务开发人员来说,并不用关心到底是 Connection 是什么实现,我只需要定义好对应数据库的驱动程序即可。
  抽象工厂 Abstract Factory
  抽象工厂是在工厂方法之上的又一次扩展,随着产品的复杂度提高,工厂方法以及不能适应更多产品的生产,拿面食工厂举例,时间久了,大家对面食的种类产生了疑惑,为啥没有馒头?要求面食工厂能生产馒头,那么好,现在有两位师傅,一个是老干妈,一个是老干爹,从现在开始让他们生产馒头,我们工厂现在的产品种类有包子和馒头(哪天说不定还有花卷),在这种支持产品种类会有扩展的场景,就需要抽象工厂设计模式来搞定了。集合 UML 类图理解一下抽象工厂:
png
抽象工厂适合产品种类会扩展的场景,但是这种模式也有弊端,在进行产品种类扩展的同时,也会去修改已有的工厂类,添加新的产品生产接口,这个违背了开闭原则,因此要谨慎使用。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3165 引用 • 8206 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    198 引用 • 120 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 506 关注
  • CodeMirror
    1 引用 • 2 回帖 • 109 关注
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    85 引用 • 1192 回帖 • 461 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    914 引用 • 930 回帖 • 1 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 545 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    163 引用 • 1446 回帖 • 1 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 598 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1397 回帖
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 594 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    106 引用 • 152 回帖 • 2 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    284 引用 • 4481 回帖 • 651 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    37 引用 • 24 回帖 • 1 关注
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    35 引用 • 35 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 1 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 638 关注
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 596 关注
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 676 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    89 引用 • 113 回帖
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 591 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 16 关注
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    362 引用 • 1212 回帖 • 580 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 591 关注
  • OnlyOffice
    4 引用 • 19 关注
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    169 引用 • 799 回帖