news 2026/6/29 9:05:02

创建型模式:对象的诞生艺术

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
创建型模式:对象的诞生艺术

写代码绕不开new。但当系统复杂到一定程度,你会发现到处散落的new是个大麻烦:

  • 改一个类的构造方式,满世界找new的地方改
  • 想根据条件创建不同对象,写出一堆if-else
  • 对象创建过程太复杂,几十行初始化代码到处复制

创建型模式就是来治这些病的。一共 5 种,下面逐个拆解。

创建型模式关心的核心问题只有一个:对象怎么来的?把"怎么创建对象"这件事封装起来,让使用者不需要知道细节,拿来就用。


一、单例模式(Singleton)

一句话

一个类在整个系统里只有一个实例,谁来要都给同一个。

生活中的例子

  • 公司打印机:整个办公室共用一台打印机,不是每人发一台。你提交打印任务,和同事提交打印任务,都是发到同一台打印机。
  • Windows 任务管理器:不管你按多少次 Ctrl+Shift+Esc,打开的都是同一个窗口,不会弹出来两个。

为什么需要它

有些东西天生只该有一份:

  • 配置管理器:配置只需要读一次,全局共享
  • 数据库连接池:连接是昂贵资源,不能每次new一个
  • 日志器:所有模块往同一个地方写日志
  • 应用的全局缓存:数据只有一份,避免不同缓存实例数据不一致

如果不做限制,每个角落都new一份,轻则浪费内存,重则数据不一致。比如两个配置管理器实例,一个读了新配置,另一个还是老的——系统行为就乱套了。

示意图

代码实现

java实现(双重检查锁)

Python 实现

Python 线程安全版本:

注意事项

问题说明解法
多线程安全两个线程同时判断 instance 为空,创建出两个加锁 / 双重检查 / 枚举
反射攻击Java 反射可以强行调用私有构造器枚举实现可防;或在构造器里加判断
序列化问题反序列化会绕过构造器创建新对象readResolve()方法
测试困难全局状态难以 mock配合依赖注入框架使用

二、工厂方法模式(Factory Method)

一句话

定义一个创建对象的接口,让子类决定实例化哪个类。

生活中的例子

  • 披萨连锁店:总部定义了"做披萨"的标准流程(揉面、放料、烤制),但北京店做的是宫保鸡丁披萨,纽约店做的是芝士披萨。"做什么口味"这个决定权交给各分店。
  • 物流公司:客户只说"帮我发货",但走陆运还是空运还是海运,由物流公司根据情况决定用哪种运输工具。
  • 手机工厂:你下单买一部手机,富士康帮你组装。同样的产线,装不同的零件就出不同型号。

为什么需要它

假设你在做一个文档导出功能:

java

// 这样写,每加一种格式就要改这段代码 if (type.equals("pdf")) { return new PdfExporter(); } else if (type.equals("excel")) { return new ExcelExporter(); } else if (type.equals("word")) { return new WordExporter(); } // 后来又加了 csv、html、markdown... 这段代码改到崩溃

每次新增格式都要回来改这段代码,改一次就有一次出 bug 的风险。这违反了开闭原则(对扩展开放,对修改关闭)。

结构图


工厂方法里有两条独立的"继承/实现链",这两条链是平行存在的,一条管"谁来造",一条管"造出来的东西长什么样"。
工厂:ExportFactory是抽象类,子类继承它
产品:Exporter是接口,实现类实现它

为什么这样设计?
ExportFactory是抽象类而不是接口,因为它里面有公共代码可以复用:

java

// 这段逻辑所有工厂都一样,写在抽象类里复用 public void export(Data data, OutputStream out) { Exporter exporter = createExporter(); // 调子类实现的方法 byte[] result = exporter.render(data); out.write(result)

子类只需要实现createExporter()这一个方法就够了,其余逻辑继承父类。

Exporter是接口,因为产品只需要约定"你必须有render()方法",没有任何公共代码可以共享,所以用接口更合适。

代码实现

java实现

python实现

新增格式?写一个新的 Factory + Exporter 就行,原有代码一行不动


三、抽象工厂模式(Abstract Factory)

一句话

提供一个接口,创建一系列相关的对象,而不指定具体类。

生活中的例子

  • 宜家家具套装:你选了"北欧风格",那椅子、桌子、沙发、柜子全是北欧风的。你选了"中式风格",全套都是中式。不会出现北欧椅子配中式桌子的混搭。
  • 手机生态:买了苹果手机,充电器是 Lightning/USB-C、耳机是 AirPods、手表是 Apple Watch——一整套生态。买安卓则是另一套。
  • 游戏皮肤:选了"暗黑主题",角色、武器、坐骑、特效全部是暗黑风格的配套。

和工厂方法的区别

  • 工厂方法:一个工厂造一种产品
  • 抽象工厂:一个工厂造一族产品(多种产品配套)
工厂方法抽象工厂
一个工厂造几种产品一种一族(多种)
解决什么问题让子类决定造哪种产品保证一整套产品风格一致
例子PdfFactory 只造 PdfExporterMacFactory 造 Mac 全套 UI
抽象的是什么一个创建方法一组创建方法
创建方法createExporter() — 只有一个createButton() + createInput() + createDialog() — 多个

"抽象工厂"的"抽象"更准确的理解是:把创建一整族相关产品这件事抽象成了一个接口,强调的是"族",而不只是单个产品。

结构图

代码实现

java实现

python实现

四、建造者模式(Builder)

一句话

分步骤构建一个复杂对象,同样的构建过程可以创建不同的表示。

生活中的例子

  • 点汉堡套餐:你可以自选面包类型、肉饼种类、是否加芝士、是否加生菜、要什么酱料、配什么饮料。一步步选,最后组装成一个完整的套餐。
  • 装修房子:地板选什么材质、墙面刷什么颜色、厨房用什么台面、卫生间装什么花洒……一项项确定,最后交付一个完整的房子。
  • 写简历:先填基本信息,再填教育经历,再填工作经验,再填技能……不是一次性传 20 个参数,而是分步骤填充。

为什么需要它

当一个对象有十几个参数,构造器会变成噩梦:

java

// 看到这种代码你能分清哪个参数是什么吗? new House(4, 2, true, false, true, "木质", null, 3, true, "现代");

这段代码有三个真实的痛点:
看不懂:7 个参数,没有名字,只有顺序,读代码要来回对照类定义
传错了不报错:true 和 false 顺序写反了,编译器不会提示,运行时悄悄出 bug
可选参数很麻烦:有些房子没泳池,你得要么传 false,要么写一堆重载构造器

参数一多,顺序一乱就出 bug。有些参数是可选的,有些有默认值,用构造器重载的话要写几十个重载方法。


Builder 怎么解决问题的:

java

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/29 9:03:04

实战XSS防御:从前端到后端的纵深安全体系构建

1. 项目概述:从一次真实的XSS攻击说起 去年,我们团队负责的一个面向C端用户的社区产品上线不久,运营同事就慌慌张张地跑过来,说后台收到大量用户投诉,点开某些帖子后页面会疯狂弹窗,甚至自动跳转到一些奇怪…

作者头像 李华
网站建设 2026/6/29 9:01:42

Gemini Study Notebooks 是什么:Google 把 AI 学习笔记做成了什么样

Google 在 2026 年 6 月更新 Gemini app,加入了 Study notebooks。它不是单纯的聊天入口,也不是传统笔记软件,而是一个围绕学习目标组织材料、提问、解释和复习的 AI 学习空间。 这类功能值得关注的原因,不是“又多了一个 AI 笔记工具”,而是它代表了 AI 工具的一个变化:…

作者头像 李华
网站建设 2026/6/29 9:01:09

C语言实现栅栏密码:从算法原理到健壮代码实践

1. 项目概述:从“栅栏”到“密文”最近在整理一些古典密码学的实现,发现很多初学者对“栅栏密码”这个概念既熟悉又陌生。熟悉是因为它在很多CTF(Capture The Flag)竞赛和入门密码学教程里常作为第一道“开胃菜”出现;…

作者头像 李华
网站建设 2026/6/29 8:59:01

BetterGI安装失败怎么办?三步诊断与修复方案详解

BetterGI安装失败怎么办?三步诊断与修复方案详解 【免费下载链接】better-genshin-impact 📦BetterGI 更好的原神 - 自动拾取 | 自动剧情 | 全自动钓鱼(AI) | 全自动七圣召唤 | 自动伐木 | 自动刷本 | 自动采集/挖矿/锄地 | 一条龙 | 全连音游 | 自动烹…

作者头像 李华
网站建设 2026/6/29 8:53:13

AI驱动测试用例生成:原理、实践与Ralph方案解析

1. 项目概述:当AI代理遇上测试用例生成最近在团队里折腾自动化测试,一个老生常谈的痛点又浮出水面:编写和维护测试用例,尤其是那些覆盖各种边界条件和复杂业务逻辑的用例,耗时耗力,还容易遗漏。测试工程师和…

作者头像 李华
网站建设 2026/6/29 8:48:38

python爬虫实战项目|第70篇:爬虫系列文章回顾与进阶路径

概述 本篇文章作为爬虫系列的阶段性总结,将系统性地回顾从基础概念到高级应用的核心知识点,梳理技术脉络,为读者提供清晰的进阶学习路径。同时探讨爬虫技术的未来发展趋势,帮助读者把握技术方向,规划个人成长路线。 1. 技术体系全景图 1.1 知识架构总览 爬虫技术体系 …

作者头像 李华