☰
Java 简单工厂模式(Simple Factory Pattern)实战指南:以 java-design-patterns 的 CoinFactory 为例
2026/10/2 1:56:51 网站建设 项目流程
  • 示例工程
  • 教程

【免费下载链接】java-design-patterns

Design patterns implemented in Java

项目地址:https://gitcode.com/GitHub_Trending/ja/java-design-patterns
点击查看免费下载

导读

本文围绕 java-design-patterns 仓库中 factory 模块 的完整实现,系统讲解简单工厂模式(Simple Factory,也称静态工厂方法 Static Factory Method)的核心思想、UML 结构与源码实现。你将掌握如何用一个封装了静态工厂方法的类隐藏对象创建逻辑,让客户端只关心"用什么"而不关心"怎么造",并理解它与 Factory Method、Abstract Factory、Factory Kit 等创建型模式的边界。

一、模式概览:它是什么,为什么需要它

简单工厂模式属于创建型模式(Creational Pattern)中的一种(分类标签为 Gang of Four 相关模式)。其核心做法是:将对象创建的实现逻辑封装在名为 factory 的类中,向客户端暴露一个静态方法。客户端调用该方法时只需传入类型参数,即可获得对应实例,从而把注意力从"初始化新对象"转移到"使用对象"上。

在 localization/ko/factory/README.md(本文的韩文关联文档)与 factory/README.md(英文主文档)中,官方给出的意图如下:

提供封装在 factory 类中的静态方法,隐藏实现逻辑,使客户端代码专注于对象的使用而非初始化。

Wikipedia 对 factory 的定义同样简洁:

Factory 是用于创建其他对象的对象。正式地说,factory 是返回可变原型或类对象的函数或方法。

现实场景举例

一个 SQLServer 连接的 Web 应用需要切换到 Oracle,且不想修改既有源代码。此时可以引入 Simple Factory:通过静态方法为给定数据库创建连接对象,客户端无需感知数据库驱动差异。

这一场景揭示了简单工厂最典型的价值:把"创建什么、如何创建"的决策集中到一处,当需求变化(如切换数据库、新增产品类型)时,只改动工厂内部,客户端代码保持稳定。

二、源码级实现:CoinFactory 炼金术士造币示例

factory 模块用"炼金术士铸造金币/铜币"作为示例,完整代码位于 factory/src/main/java/com/iluwatar/factory 目录下,共包含 6 个类文件:

角色类文件路径
抽象产品Coin接口Coin.java
具体产品GoldCoin、CopperCoinGoldCoin.java、CopperCoin.java
产品类型枚举CoinTypeCoinType.java
工厂类CoinFactoryCoinFactory.java
客户端入口AppApp.java

1. 抽象产品:Coin接口

public interface Coin { String getDescription(); }

抽象产品定义了所有具体产品必须实现的行为契约。这里只有一个getDescription()方法,用于返回对产品类型的文字描述。

2. 具体产品:GoldCoin与CopperCoin

public class GoldCoin implements Coin { static final String DESCRIPTION = "This is a gold coin."; @Override public String getDescription() { return DESCRIPTION; } }
public class CopperCoin implements Coin { static final String DESCRIPTION = "This is a copper coin."; @Override public String getDescription() { return DESCRIPTION; } }

两个具体产品都实现了Coin接口,各自维护一个DESCRIPTION常量。从源码结构可以推断:后续若需新增产品(如银币SilverCoin),只需新增一个实现Coin的类并在枚举中注册,无需触碰现有类——这正是简单工厂在开闭原则上的贡献。

3. 产品类型枚举:CoinType

@RequiredArgsConstructor @Getter public enum CoinType { COPPER(CopperCoin::new), GOLD(GoldCoin::new); private final Supplier<Coin> constructor; }

CoinType是简单工厂的"类型注册表"。它利用 Java 8 的Supplier<Coin>函数式接口,将构造函数引用(CopperCoin::new、GoldCoin::new)存储为枚举常量字段。配合 Lombok 的@RequiredArgsConstructor(生成接收Supplier<Coin>的构造器)与@Getter(生成getConstructor()访问器),枚举本身就成为了一张"类型 → 构造器"的映射表。

4. 工厂类:CoinFactory

public class CoinFactory { /** Factory method takes as a parameter the coin type and calls the appropriate class. */ public static Coin getCoin(CoinType type) { return type.getConstructor().get(); } }

CoinFactory是简单工厂的核心。它只暴露一个静态方法getCoin(CoinType type),方法体内没有任何 if-else 分支:通过type.getConstructor().get()直接委托给CoinType枚举持有的Supplier完成实例化。这种"枚举驱动"的实现比传统 if-else 版本更简洁、更易扩展——新增币种时枚举与产品类成对添加即可。

5. 客户端入口:App

@Slf4j public class App { /** Program main entry point. */ public static void main(String[] args) { LOGGER.info("The alchemist begins his work."); var coin1 = CoinFactory.getCoin(CoinType.COPPER); var coin2 = CoinFactory.getCoin(CoinType.GOLD); LOGGER.info(coin1.getDescription()); LOGGER.info(coin2.getDescription()); } }

客户端只做了两件事:调用静态工厂方法拿到实例,然后使用实例。整个代码中不出现new Coin(...)之类的直接实例化,对象的创建完全被隔离在工厂层。程序运行输出:

06:19:53.530 [main] INFO com.iluwatar.factory.App -- The alchemist begins his work. 06:19:53.533 [main] INFO com.iluwatar.factory.App -- This is a copper coin. 06:19:53.533 [main] INFO com.iluwatar.factory.App -- This is a gold coin.

注:韩文关联文档中使用的示例为Car(Ford/Ferrari)与CarsFactory,代码结构与本仓库Coin/CoinFactory完全同构;本文以仓库实际源码为准展开讲解。

三、UML 类图与调用时序

factory 模块的 etc 目录下提供了两张官方示意图,准确刻画了简单工厂的结构与交互。

类图:五种角色的静态关系

类图清晰展示了简单工厂的完整角色结构:抽象产品Coin(接口)位于顶层,GoldCoin、CopperCoin分别实现它;CoinType枚举记录了类型与构造器的映射;CoinFactory作为工厂负责生产;App作为调用端完成整个工厂调用流程。这张图直接对应了 factory.urm.puml 源文件。

时序图:客户端与工厂的交互流程

时序图还原了简单工厂的运行逻辑:客户端(Client)向工厂(Factory)发起创建产品请求,工厂依据类型调用对应产品的实例化方法,最后将实例返回给客户端。整个过程中客户端只与工厂交互,完全感知不到具体产品的构造细节。

四、测试验证:工厂行为如何被保障

factory 模块自带两个 JUnit 5 测试,用于验证工厂的核心行为:

CoinFactoryTest—— CoinFactoryTest.java:

class CoinFactoryTest { @Test void shouldReturnGoldCoinInstance() { final var goldCoin = CoinFactory.getCoin(CoinType.GOLD); assertTrue(goldCoin instanceof GoldCoin); } }

该测试断言CoinFactory.getCoin(CoinType.GOLD)返回的实例确实是GoldCoin类型,直接验证了"工厂根据枚举类型返回正确具体产品"这一核心职责。

AppTest—— AppTest.java:

class AppTest { @Test void shouldExecuteWithoutExceptions() { assertDoesNotThrow(() -> App.main(new String[] {})); } }

该测试验证App.main的完整调用链(含工厂调用与日志输出)能无异常执行,保证示例程序的端到端可用性。

五、适用场景与使用建议

根据官方文档,当以下情况出现时适合使用简单工厂:

  • 类事先不知道它需要创建的对象的确切类型和依赖;
  • 一个方法需要返回共享同一父类/接口的多个可能类之一,且希望封装"创建哪个对象"的决策逻辑;
  • 在设计框架或类库时,希望获得对具体类类型的最佳灵活性与隔离性。

结合源码进一步解读:

  • 集中创建逻辑:所有对象创建集中在一处(CoinFactory),避免代码库中散落new关键字,从源码结构看,factory/src/main/java下唯一的实例化入口就是工厂方法内部的Supplier.get()。
  • 松散耦合:客户端仅依赖Coin抽象与CoinType枚举,不依赖GoldCoin/CopperCoin具体类,因此更利于测试(可注入 mock 产品)、组件替换与功能扩展。

六、优点与代价

优点

  • 创建集中管理:所有对象创建保持在一处,防止new关键字在代码库中蔓延;
  • 降低耦合:写出松散耦合的代码,带来更好的可测试性、更易读的代码、可替换的组件、可扩展性与功能隔离;
  • 符合开闭原则:系统可在不修改现有代码的前提下引入新类型(新增产品类 + 枚举注册即可)。

代价

  • 代码复杂度上升:引入多个附加类(抽象产品、具体产品、枚举、工厂)后,代码比直接实例化复杂;
  • 可能过度设计:如果对象创建本身逻辑简单、复杂度低,过度使用会降低代码可读性。韩文文档对此的表述是"代码比想象中更复杂"。

七、相关模式辨析

简单工厂常与以下模式对照使用:

模式关系说明仓库模块
Factory Method(工厂方法)更"正统"的 GoF 模式,通过子类重写工厂方法决定实例化哪个类;简单工厂可视为其特例或简化版factory-method
Factory Kit(工厂套件)一种将 builder 与 factory 接口分离的"不可变内容工厂",比简单工厂更灵活factory-kit
Abstract Factory(抽象工厂)可看作工作在"一组产品"之上的工厂,用于创建相互关联的产品族abstract-factory
Singleton(单例)常与工厂搭配使用,确保某个类只有一个实例singleton
Builder(建造者)将复杂对象的构造与其表示分离,与工厂管理实例化的思路互补builder

八、如何在本地运行与验证

factory 是 Maven 多模块项目中的一个独立子模块(见 factory/pom.xml),仓库根目录提供了 Maven Wrapper(mvnw)。在仓库根目录执行以下命令即可编译、运行测试并查看示例输出:

# 编译并运行 factory 模块的全部测试(CoinFactoryTest、AppTest) ./mvnw -pl factory test # 若需直接运行 App 主类查看程序输出 ./mvnw -pl factory exec:java -Dexec.mainClass="com.iluwatar.factory.App"

提示:mvnw为 Maven Wrapper 脚本,无需预先安装 Maven;执行测试可观察CoinFactoryTest对CoinType.GOLD → GoldCoin的断言通过。

结语

简单工厂是创建型模式中最小巧、最易上手的一种。本仓库的 factory 模块用"炼金术士造币"这个不足百行的例子,展示了从抽象产品、具体产品、类型枚举到静态工厂方法的完整套路;枚举 +Supplier的写法更是消除了传统 if-else 分支,让扩展新币种变成"加一个类、加一个枚举常量"两件事。掌握它之后,再对比 factory-method、factory-kit 与 abstract-factory 模块,你就能建立起对创建型模式家族的整体认知。

  • 示例工程
  • 教程

【免费下载链接】java-design-patterns

Design patterns implemented in Java

项目地址:https://gitcode.com/GitHub_Trending/ja/java-design-patterns
点击查看免费下载

相关推荐

上一篇:dockview部署指南:从开发到生产环境的完整流程
下一篇:Awesome-Computer-Vision-Paper-List的API开发指南:构建个性化研究工具

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询