news 2026/9/26 16:17:30

工厂方法模式:把创建延迟到子类

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
工厂方法模式:把创建延迟到子类

工厂方法模式:把创建延迟到子类

简单工厂把所有产品的创建逻辑塞进一个工厂类,新增产品必须修改工厂。工厂方法模式换了个思路:不再用一个工厂创建所有产品,而是为每种产品定义一个工厂,让子类决定创建什么。

这就是 GoF 23 种设计模式中的工厂方法模式。它比简单工厂更符合开闭原则,代价是类的数量成倍增加。

结构

工厂方法模式包含四个角色:

  • 抽象产品(Product):定义产品的接口
  • 具体产品(Concrete Product):实现产品接口的具体类
  • 抽象工厂(Creator):声明工厂方法,返回抽象产品
  • 具体工厂(Concrete Creator):实现工厂方法,返回具体产品

抽象工厂中通常还包含一些依赖产品的业务逻辑,这些逻辑调用工厂方法获取产品对象,但不关心具体是哪个产品。

代码实现

还是用支付作为例子。

抽象产品:

publicinterfacePayment{voidpay(doubleamount);}

具体产品:

publicclassAliPayimplementsPayment{@Overridepublicvoidpay(doubleamount){System.out.println("支付宝支付:"+amount);}}publicclassWechatPayimplementsPayment{@Overridepublicvoidpay(doubleamount){System.out.println("微信支付:"+amount);}}

抽象工厂:

publicabstractclassPaymentFactory{// 工厂方法,由子类实现publicabstractPaymentcreatePayment();// 业务逻辑,依赖工厂方法创建的产品publicvoidprocessPayment(doubleamount){Paymentpayment=createPayment();// 可以在这里加统一的处理逻辑,比如日志、校验payment.pay(amount);}}

具体工厂:

publicclassAliPayFactoryextendsPaymentFactory{@OverridepublicPaymentcreatePayment(){returnnewAliPay();}}publicclassWechatPayFactoryextendsPaymentFactory{@OverridepublicPaymentcreatePayment(){returnnewWechatPay();}}

调用方:

publicclassClient{publicstaticvoidmain(String[]args){PaymentFactoryfactory=newAliPayFactory();factory.processPayment(100);}}

调用方只依赖PaymentFactory抽象类和Payment接口,完全不接触具体类。

与简单工厂的关键区别

简单工厂是一个工厂类创建所有产品,工厂方法把创建延迟到子类,每种产品对应一个工厂类。

新增一种支付方式时:

  • 简单工厂:修改PaymentFactory的switch,加一个case。
  • 工厂方法:新增UnionPayFactory类,不动任何已有代码。

前者违反开闭原则,后者符合。这是工厂方法最核心的优势。

对比维度简单工厂工厂方法
工厂类数量1 个N 个(每个产品一个)
新增产品修改工厂类新增工厂类
开闭原则违反符合
代码复杂度低中
适用场景产品少且稳定产品多且需扩展

抽象工厂中的业务逻辑

工厂方法不只是“返回一个对象”。抽象工厂里通常还有依赖产品的业务方法,这些方法调用工厂方法获取产品,再执行通用逻辑。

publicabstractclassPaymentFactory{publicabstractPaymentcreatePayment();publicvoidprocessPayment(doubleamount){// 通用逻辑:校验、日志、记录时间System.out.println("开始处理支付...");Paymentpayment=createPayment();payment.pay(amount);System.out.println("支付处理完成");}}

子类只需要实现createPayment(),通用的处理流程由抽象类统一定义。这是模板方法模式和工厂方法模式的经典组合——抽象类定义流程骨架,子类填充具体产品的创建逻辑。

何时用工厂方法

产品种类会持续扩展。如果未来会不断增加新的产品类型,工厂方法比简单工厂更合适,因为扩展成本更低。

需要把创建和使用分离到不同层次。框架设计常用工厂方法,让框架定义抽象工厂,具体产品由使用方通过子类提供。

产品创建有复杂逻辑。每个产品可能有不同的初始化步骤,放在各自的工厂类里更清晰。

不希望调用方依赖具体产品类。调用方只认识抽象工厂和抽象产品,具体类完全隐藏。

何时不用

产品种类少且稳定。如果只有两三种产品,未来也不会增加,简单工厂足够,工厂方法反而增加了不必要的类。

不需要扩展点。如果整个系统只有一处地方需要创建对象,抽象出工厂类意义不大。

类和接口已经很多了。工厂方法会让类数量翻倍,如果项目本身结构复杂,要谨慎权衡。

在 Spring 中的体现

Spring 的FactoryBean接口是工厂方法模式的一个变体:

publicinterfaceFactoryBean<T>{TgetObject()throwsException;Class<?>getObjectType();booleanisSingleton();}

getObject()就是工厂方法。你可以通过实现FactoryBean来定制复杂对象的创建过程,Spring 容器在getBean()时会调用getObject()返回真正的对象。

Spring 的BeanFactory体系本身也是工厂模式的集大成者。BeanFactory是抽象工厂,XmlBeanFactory、AnnotationConfigApplicationContext等是具体工厂,它们负责创建和管理 Bean。

一个容易踩的坑

抽象工厂里的工厂方法,不要在构造方法或字段初始化时调用。因为子类构造方法执行时,父类构造方法先执行,此时子类的字段还没初始化,createPayment()可能拿到不完整的对象。

publicabstractclassPaymentFactory{privatePaymentdefaultPayment=createPayment();// ❌ 危险publicabstractPaymentcreatePayment();}

正确做法是在业务方法中调用,而不是在构造阶段。

总结

维度说明
核心思想定义创建对象的接口,让子类决定实例化哪个类
角色抽象产品、具体产品、抽象工厂、具体工厂
与简单工厂的区别每种产品一个工厂,扩展时新增类而非修改已有代码
优点符合开闭原则,创建与使用分离,职责清晰
缺点类数量增加,抽象层次提高
典型组合与模板方法模式配合,抽象类定义流程,子类实现创建
Spring 体现FactoryBean、BeanFactory体系

工厂方法模式解决的是“新增产品要改工厂”的问题,代价是多了一层继承体系。当产品种类会持续增长,或者需要把创建逻辑下放到子类时,它是比简单工厂更合适的选择。

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

排队论与指数分布:工业工程中的瓶颈与产能优化

1. 为什么排队问题是工业工程的"隐形减速带"1.1 一个真实的车间场景你有没有遇到过这样的车间&#xff1a;流水线上的设备利用率看起来并不低&#xff0c;报表显示每台机器一天开机七八个小时&#xff0c;但订单交付就是一直拖延&#xff0c;在制品堆得到处都是&…

作者头像 李华