新闻详情

新闻详情

首页 / 资讯中心 / 详情

java-design-patterns 工厂方法模式(Factory Method)实战解析:用铁匠锻造武器的多态制造

发布时间:2026/10/2 1:56:46来源:尧图网络
java-design-patterns 工厂方法模式(Factory Method)实战解析:用铁匠锻造武器的多态制造
示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载工厂方法Factory Method是 GoF 二十三式中最基础也最常用的创建型模式之一它把“创建哪种对象”的决定权从调用方手中移交到子类手中让代码只依赖产品接口而非具体类。本文以 java-design-patterns 仓库中的 factory-method 模块黑铁匠锻造武器的经典示例为骨架结合源码、测试与 UML 图完整讲解该模式的意图、实现、适用场景与在 JDK 中的真实应用读完即可在自己的 Java 项目中落地这套“多态制造”方案。模式一览别名与定位别名虚拟构造函数Virtual Constructor分类创建型模式CreationalGang of Four 标签可扩展性Extensibility、封装Encapsulation、实例化Instantiation、多态Polymorphism核心思想定义一个用于创建对象的接口让子类决定实例化哪一个具体类把对象创建逻辑从使用方抽离出来该模式的完整英文文档位于 factory-method/README.md本文对应的印地语翻译版位于 localization/hi/factory-method/README.md。模式意图将实例化延迟到子类根据模式定义工厂方法的意图可以概括为一句话定义一个用于创建对象的接口但让子类决定实例化哪个类。工厂方法使一个类能够把实例化推迟到子类中进行。这意味着上层代码在编译期并不知道也不关心最终创建出来的对象是什么具体类型——它只面向“产品接口”编程。真正决定“造什么”的逻辑被封装在工厂接口的实现类即各具体工厂中从而实现了创建逻辑的隔离与复用。现实世界类比铁匠锻造武器要理解工厂方法最直观的例子就是铁匠铺场景设定铁匠负责打造武器。精灵族需要精灵武器elven weapons兽人族需要兽人武器orcish weapons。关键约束究竟召唤哪位铁匠取决于当前到店的客户是谁。中央系统调用方不需要知道每种武器的锻造细节只需要说“我要一把长矛”剩下的交给正确的铁匠。这正是工厂方法模式在现实中的映射客户端只表达“需求”What具体“怎么做”How与“做成什么”Which concrete class由具体工厂决定。用一句大白话概括模式本质它提供了一种把实例化逻辑委托给子类的方式。模式定义从 GoF 与维基百科视角看原理维基百科对工厂方法模式的经典定义也被本仓库 README 引用为在基于类的编程中工厂方法模式是一种创建型模式它利用工厂方法解决“在不指定将要创建对象的确切类的前提下创建对象”的问题。做法是通过调用工厂方法而非直接调用构造函数来创建对象——该工厂方法要么在接口中声明并由子类实现要么在基类中实现并由派生类可选地覆写。这段定义拆解出两个关键机制接口 子类实现工厂方法在接口或抽象基类中声明由具体子类实现——本仓库的Blacksmith接口采用的就是这种形式基类默认实现 派生类覆写工厂方法在基类中提供默认实现派生类按需覆写这是另一种常见变体。无论哪种变体共同点都是用一次方法调用替代new运算符将“创建对象”这一动作变成可覆写、可扩展的扩展点。程序化示例铁匠与武器源码逐层拆解本仓库的 factory-method 模块位于 factory-method/src/main/java/com/iluwatar/factory/method完整代码共 8 个文件下面按“产品 → 工厂 → 客户端”的顺序逐层拆解。第一步产品接口与产品实现所有被创建的对象都实现同一个产品接口Weapon客户端只与它打交道// Weapon.java public interface Weapon { WeaponType weaponType(); }两个具体产品使用 Java 的 record 实现分别代表精灵武器与兽人武器// ElfWeapon.java public record ElfWeapon(WeaponType weaponType) implements Weapon { Override public String toString() { return an elven weaponType; } } // OrcWeapon.java public record OrcWeapon(WeaponType weaponType) implements Weapon { Override public String toString() { return an orcish weaponType; } }两个 record 都覆写了toString()这正是后面程序输出中 “an elven spear”“an orcish axe” 等文案的来源见 ElfWeapon.java 与 OrcWeapon.java。第二步武器类型枚举WeaponType枚举定义了可制造的武器种类并为每种类型绑定可读标题// WeaponType.java RequiredArgsConstructor public enum WeaponType { SHORT_SWORD(short sword), SPEAR(spear), AXE(axe), UNDEFINED(); private final String title; Override public String toString() { return title; } }可见本示例支持SHORT_SWORD、SPEAR、AXE三种真实武器类型以及一个哨兵值UNDEFINED见 WeaponType.java。第三步工厂接口与两个具体工厂工厂接口声明唯一的工厂方法manufactureWeapon入参是武器类型返回值是产品接口Weapon// Blacksmith.java public interface Blacksmith { Weapon manufactureWeapon(WeaponType weaponType); }两个具体工厂ElfBlacksmith与OrcBlacksmith实现了该接口。值得注意的实现细节是它们各自用一个静态EnumMap作为“军械库”缓存在类加载时一次性把所有类型的武器预生成好制造时直接查表返回避免重复创建// ElfBlacksmith.java public class ElfBlacksmith implements Blacksmith { private static final MapWeaponType, ElfWeapon ELFARSENAL; static { ELFARSENAL new EnumMap(WeaponType.class); Arrays.stream(WeaponType.values()).forEach(type - ELFARSENAL.put(type, new ElfWeapon(type))); } Override public Weapon manufactureWeapon(WeaponType weaponType) { return ELFARSENAL.get(weaponType); } Override public String toString() { return The elf blacksmith; } } // OrcBlacksmith.java结构对称 public class OrcBlacksmith implements Blacksmith { private static final MapWeaponType, OrcWeapon ORCARSENAL; static { ORCARSENAL new EnumMap(WeaponType.class); Arrays.stream(WeaponType.values()).forEach(type - ORCARSENAL.put(type, new OrcWeapon(type))); } Override public Weapon manufactureWeapon(WeaponType weaponType) { return ORCARSENAL.get(weaponType); } Override public String toString() { return The orc blacksmith; } }从源码结构可以推断出两点设计意图静态缓存 枚举键EnumMap以枚举为键、按枚举序存储相比HashMap更省内存、访问更快静态块确保军械库只初始化一次见 ElfBlacksmith.java覆写toString()让日志输出中的“The orc blacksmith / The elf blacksmith”读起来像真实叙述。第四步客户端调用与程序输出客户端入口类App只面向Blacksmith接口编程先召唤兽人铁匠造长矛和斧头再换成精灵铁匠造同样两件武器全程不知道也不关心具体武器类// App.java Slf4j public class App { private static final String MANUFACTURED {} manufactured {}; public static void main(String[] args) { Blacksmith blacksmith new OrcBlacksmith(); Weapon weapon blacksmith.manufactureWeapon(WeaponType.SPEAR); LOGGER.info(MANUFACTURED, blacksmith, weapon); weapon blacksmith.manufactureWeapon(WeaponType.AXE); LOGGER.info(MANUFACTURED, blacksmith, weapon); blacksmith new ElfBlacksmith(); weapon blacksmith.manufactureWeapon(WeaponType.SPEAR); LOGGER.info(MANUFACTURED, blacksmith, weapon); weapon blacksmith.manufactureWeapon(WeaponType.AXE); LOGGER.info(MANUFACTURED, blacksmith, weapon); } }程序输出日志格式与 App.java 中的LOGGER.info调用一一对应The orc blacksmith manufactured an orcish spear The orc blacksmith manufactured an orcish axe The elf blacksmith manufactured an elven spear The elf blacksmith manufactured an elven axe注意输出中的 “orcish / elven” 分别来自OrcWeapon、ElfWeapon的toString()而 “spear / axe” 来自WeaponType枚举的title字段——文案在多层对象间各司其职这也是“产品自描述”的典型体现。类图与调用时序下图是工厂方法模式在本仓库中的完整类图PlantUML 源文件见 factory-method.urm.puml类图清晰地展示了四条关键关系ElfBlacksmith与OrcBlacksmith都实现Blacksmith接口..|ElfWeapon与OrcWeapon都实现Weapon产品接口App通过字段依赖Blacksmith接口--实现面向接口编程每个具体工厂内部维护各自的武器 MapELFARSENAL/ORCARSENAL。仓库还提供了调用时序图直观展示“客户端 → 具体工厂 → 具体产品”的调用链如何运行与验证该模块是标准 Maven 子模块见 factory-method/pom.xml其pom.xml中已将主类配置为com.iluwatar.factory.method.Appmaven-assembly-plugin的 manifest 配置依赖仅包含 slf4j、logback 与 JUnit 5非常轻量。在仓库根目录下可用以下命令运行与验证# 运行模块测试含工厂方法核心测试用例 ./mvnw -pl factory-method test # 或连同父 POM 一起构建 ./mvnw -pl factory-method -am package测试方面FactoryMethodTest.java 用 JUnit 5 编写了四个用例分别验证OrcBlacksmith造出的SPEAR必须是OrcWeapon实例且weaponType()为SPEAROrcBlacksmith造出的AXE必须是OrcWeapon实例且类型正确ElfBlacksmith造出的SHORT_SWORD必须是ElfWeapon实例且类型正确ElfBlacksmith造出的SPEAR必须是ElfWeapon实例且类型正确。其中verifyWeapon辅助方法同时断言“实例类型正确”与“武器类型正确”两个维度见 FactoryMethodTest.java——这组测试本质上就是在验证工厂方法模式的承诺“找对工厂就能造出对的产品”。另有 AppTest.java 负责入口类的冒烟测试。适用场景根据官方文档英文版与印地语版一致以下三种情况适合使用工厂方法模式类无法预知它必须创建的对象属于哪个类——即创建目标在编译期不确定类希望由子类来指定它所创建的对象——把创建点做成扩展点交给子类按需定制类将责任委托给多个辅助子类之一并希望“哪个辅助子类是被委托者”的知识被局部化——把选择逻辑收敛在工厂内部调用方无需感知。反之如果产品类型在编译期完全确定、也没有子类化扩展的诉求直接new反而更简单——工厂方法是为“变化的创建点”而生的。JDK 中的真实应用工厂方法在 JDK 中无处不在官方文档列出的代表性 API 包括均为“通过静态工厂方法获取实例、内部隐藏具体类”的经典案例java.util.Calendar#getInstance()——按当前时区/语言环境返回具体日历子类java.util.ResourceBundle#getBundle(String)——按资源包基名返回具体 Bundle 实现java.text.NumberFormat#getInstance()——按语言环境返回具体数字格式化器java.nio.charset.Charset#forName(String)——按字符集名称返回具体 Charset 实现java.net.URLStreamHandlerFactory#createURLStreamHandler(String)——按协议返回对应的处理器java.util.EnumSet#of(E)——按元素数量智能选择RegularEnumSet或JumboEnumSetjavax.xml.bind.JAXBContext#createMarshaller()——创建序列化器实例。这些 API 的共同点与Blacksmith#manufactureWeapon完全一致调用方只传参数、只拿接口具体类由工厂内部决定这正是工厂方法模式在真实工业代码中的生命力所在。模式优点与代价优点为子类提供“钩子”hooks创建点成为可覆写扩展点新增产品族只需新增具体工厂与具体产品符合开闭原则连接平行的类层次结构工厂类层次与产品类层次一一对应、职责清晰消除对应用特定具体类的硬编码绑定代码只依赖产品接口因此可以配合任何用户自定义的具体产品类使用增强了灵活性与可维护性。代价需要为每个新的具体工厂引入新的子类当产品种类激增时类数量会随之膨胀可能让代码结构变复杂。这是“用类数量换取解耦”的典型取舍。相关模式抽象工厂模式Abstract Factory抽象工厂通常聚合多个工厂方法工厂方法常作为抽象工厂内部创建单个产品的手段原型模式Prototype工厂方法也可用于返回“原型对象的克隆实例”此时工厂方法内部走clone而非new。参考与延伸阅读本文核心文档localization/hi/factory-method/README.md印地语版与 factory-method/README.md英文版完整源码factory-method/src/main/java/com/iluwatar/factory/method单元测试factory-method/src/test/java/com/iluwatar/factory/method类图与时序图factory-method/etc/factory-method.urm.png、factory-method/etc/factory-method-sequence-diagram.png源文件为 factory-method/etc/factory-method.urm.puml经典书籍《Design Patterns: Elements of Reusable Object-Oriented Software》GoF、《Head First Design Patterns》与《Refactoring to Patterns》对工厂方法的阐述即为本模式的理论源头总而言之工厂方法模式用一次“多态制造”完成了两件事对外客户端获得稳定的产品接口对内创建逻辑随子类分化、按需扩展。当你在项目中遇到“创建点会变、类型不确定”的场景时回到这份铁匠铺示例就能快速套用出一套解耦而优雅的方案。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐Java 设计模式实战工厂方法模式Factory Method在 java-design-patterns 中的完整实现剖析Java 设计模式实战工厂方法模式Factory Method在 java design patterns 中的完整实现剖析 工厂方法Factory M示例工程教程java-design-patterns 工厂模式Factory深度解析简单工厂与静态工厂方法在 Coin 铸造中的落地实践java design patterns 工厂模式Factory深度解析简单工厂与静态工厂方法在 Coin 铸造中的落地实践 导读 本文以 java de示例工程教程Factory Kit 工厂套件模式实战解析用 java-design-patterns 仓库打造可配置的对象工厂Factory Kit 工厂套件模式实战解析用 java design patterns 仓库打造可配置的对象工厂 Factory Kit工厂套件是一种创示例工程教程上一篇嵌入式系统中的代码混淆技术Embedded-Engineering-Roadmap知识产权保护方案下一篇Hindsight 记忆备份 3 步指南从首次备份到故障恢复创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

用Frida-RPC实现安卓逆向:演唱会数据自动化获取实践 2026/10/2 4:31:23

用Frida-RPC实现安卓逆向:演唱会数据自动化获取实践

说实话,第一次把目标锁定在“安卓逆向 演唱会数据”这两个词上的时候,我脑子里蹦出来的第一个念头是:这东西能做成自动化吗?很多人一提逆向就想到破解、脱壳、分析so文件,一听就觉得门槛特别高。但真正把这些流程跑下…

阅读更多 →
Unity手游iOS Deep Link全链路实战:URL Scheme与Universal Links配置及参数传递 2026/10/2 4:31:17

Unity手游iOS Deep Link全链路实战:URL Scheme与Universal Links配置及参数传递

1. 为什么手游团队绕不开 Deep Link 这件事做过手游投放或者运营的兄弟应该都有体会:买量成本一年比一年高,用户点进来一次不容易,结果从浏览器点开广告、跳转到 App Store、下载、首次启动,这一整条链路上只要有一环断了&#xf…

阅读更多 →
AI+CAD落地实战:从Demo到工程化的技术难点与解决方案 2026/10/2 4:31:17

AI+CAD落地实战:从Demo到工程化的技术难点与解决方案

1. 为什么“AI CAD”的Demo看起来很美1.1 一个典型Demo的诞生过程先说说我见过最多的那类演示。打开一个网页,上传一张户型图或者机械零件的照片,点一下“生成CAD”,几秒钟后屏幕上出现一堆线条,看起来像模像样。再点一下“导出D…

阅读更多 →
速达财务SSTD3G服务器端部署全攻略:从解压到客户端连接 2026/10/2 4:30:57

速达财务SSTD3G服务器端部署全攻略:从解压到客户端连接

简介:速达财务SSTD3G_server_6.37.zip 是围绕速达财务SSTD3G系统推出的服务器端与客户端安装资源,适合中小企业财务部门及负责系统部署的IT人员使用。压缩包大小约316.81MB,已有404人学习。该安装资源覆盖服务器端与客户端两部分,…

阅读更多 →
PSO优化Kmeans聚类:居民用电行为分析实战 2026/10/2 4:30:57

PSO优化Kmeans聚类:居民用电行为分析实战

去年我接了个居民用电数据分析项目,核心目标很明确:根据智能电表采集的负荷曲线,把小区里几百户居民划分成几种典型的用电行为模式。我想着这不就是聚类嘛,直接Matlab里调个Kmeans函数分分钟搞定。结果第一版跑出来,轮…

阅读更多 →
Unity手游iOS Deep Link实战:URL Scheme与Universal Links配置及C#参数投递 2026/10/2 4:30:56

Unity手游iOS Deep Link实战:URL Scheme与Universal Links配置及C#参数投递

1. 为什么手游团队绕不开 Deep Link 这件事做过手游投放或者拉新活动的兄弟应该都有体会:买量买来的用户,点开广告之后如果只是被丢到 App Store 下载页,装完打开游戏却停在登录界面,那这个转化链路基本就废了一半。用户明明是被某…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉