Java工厂方法模式详解:从流水线到代码的智慧
一、现实中的工厂启示
场景1:汽车制造
假设某汽车公司有多个分厂:
- o 北京分厂:生产燃油车
- o 上海分厂:生产电动车
- o 广州分厂:生产混动车
总部的生产规范手册规定:
- 1. 所有分厂必须实现生产汽车()方法
- 2. 每个分厂自主决定具体车型
这就是工厂方法模式的现实映射——定义生产框架,具体实现由子类决定。
二、工厂方法模式的定义
核心思想:
定义一个创建对象的接口,但让子类决定实例化哪个类。工厂方法使类的实例化延迟到子类。
四大角色:
- 1. 抽象产品(Product):定义产品接口(如Car)
- 2. 具体产品(ConcreteProduct):实现接口的具体类(如GasCar)
- 3. 抽象工厂(Creator):声明工厂方法(如createCar())
- 4. 具体工厂(ConcreteCreator):实现工厂方法(如GasCarFactory)
UML图示:
三、代码实战:汽车生产系统
步骤1:定义产品接口
interface Car {
void startEngine();
void drive();
}
步骤2:实现具体产品
// 燃油车
classGasCarimplementsCar {
publicvoidstartEngine() {
System.out.println("点燃汽油发动机");
}
publicvoiddrive() {
System.out.println("燃油车行驶中...");
}
}
// 电动车
classElectricCarimplementsCar {
publicvoidstartEngine() {
System.out.println("启动电机");
}
publicvoiddrive() {
System.out.println("电动车静音行驶");
}
}
步骤3:定义抽象工厂
abstract classCarFactory {
// 工厂方法
publicabstract Car createCar();
// 通用业务流程
publicvoiddeliverCar() {
Carcar= createCar();
System.out.println("开始质检...");
car.startEngine();
car.drive();
System.out.println("交付完成");
}
}
步骤4:实现具体工厂
class GasCarFactoryextendsCarFactory {
@Override
public Car createCar() {
returnnewGasCar();
}
}
classElectricCarFactoryextendsCarFactory {
@Override
public Car createCar() {
returnnewElectricCar();
}
}
步骤5:客户端使用
public classClient {
publicstaticvoidmain(String[] args) {
CarFactoryfactory1=newGasCarFactory();
factory1.deliverCar();
CarFactoryfactory2=newElectricCarFactory();
factory2.deliverCar();
}
}
输出结果:
开始质检...
点燃汽油发动机
燃油车行驶中...
交付完成
开始质检...
启动电机
电动车静音行驶
交付完成
四、工厂方法的精妙设计
1. vs 简单工厂模式
简单工厂:
class SimpleCarFactory {
public static Car createCar(String type) {
if ("gas".equals(type)) return new GasCar();
else if ("electric".equals(type)) return new ElectricCar();
throw new IllegalArgumentException();
}
}
对比优势:
维度 | 简单工厂 | 工厂方法 |
扩展性 | 修改工厂类 | 新增子类即可 |
开闭原则 | 违反(修改代码) | 符合(扩展实现) |
职责划分 | 集中处理所有创建逻辑 | 分散到各子类 |
客户端耦合度 | 需要知道类型参数 | 只需选择具体工厂 |
2. 符合设计原则
- o 开闭原则:新增产品类型时无需修改已有代码
- o 单一职责:每个工厂只负责创建一种产品
- o 依赖倒置:客户端依赖抽象(Car),而非具体实现
五、典型应用场景
1. 框架扩展
案例:JDBC中的DriverManager
// 不同数据库驱动实现不同的Connection
Connection conn = DriverManager.getConnection(url);
2. 对象创建复杂
案例:Spring BeanFactory
BeanFactory factory = new XmlBeanFactory(...);
Object bean = factory.getBean("beanName");
3. 跨平台适配
案例:GUI组件库
// Windows风格按钮工厂
classWinButtonFactoryextendsButtonFactory {
public Button createButton() { returnnewWinButton(); }
}
// Mac风格按钮工厂
classMacButtonFactoryextendsButtonFactory {
public Button createButton() { returnnewMacButton(); }
}
4. 对象池管理
案例:线程池创建
ExecutorService executor = Executors.newFixedThreadPool(5);
六、实现步骤总结
- 1. 定义抽象产品接口
明确产品需要提供哪些功能 - 2. 创建具体产品类
实现不同变体的产品 - 3. 声明抽象工厂
包含工厂方法(可包含通用业务逻辑) - 4. 实现具体工厂
每个工厂对应一种产品类型 - 5. 客户端调用
通过选择具体工厂决定产品类型
七、优缺点分析
优点:
- 1. 解耦:将产品创建与使用分离
- 2. 可扩展:轻松增加新产品类型
- 3. 可维护:修改单个工厂不影响系统其他部分
- 4. 多态性:客户端通过抽象接口操作
缺点:
- 1. 类膨胀:每新增一个产品就要新增工厂类
- 2. 抽象成本:需要预先设计接口体系
- 3. 理解成本:对新手不够直观
八、常见问题解答
Q1:工厂方法 vs 抽象工厂模式?
- o 工厂方法:单个产品的创建
- o 抽象工厂:产品族的创建(多个相关产品)
Q2:什么时候选择工厂方法?
- o 需要灵活扩展产品类型时
- o 创建逻辑复杂需要封装时
- o 系统需要多态性支持时
Q3:如何处理新产品添加?
- 1. 实现新产品类(实现Product接口)
- 2. 新增对应的具体工厂类
- 3. 客户端使用新工厂
Q4:能否有多个工厂方法?
可以,例如:
abstract class MultiFactory {
public abstract ProductA createA();
public abstract ProductB createB();
}
九、在Spring框架中的应用
1. FactoryBean接口
public classCarFactoryBeanimplementsFactoryBean<Car> {
private String type;
public Car getObject() {
if ("gas".equals(type)) returnnewGasCar();
elsereturnnewElectricCar();
}
// 其他实现...
}
2. @Bean方法
@Configuration
classAppConfig {
@Bean
public Car gasCar() {
returnnewGasCar();
}
@Bean
public Car electricCar() {
returnnewElectricCar();
}
}
十、总结与提升
关键要点:
- o 工厂方法是对象创建的解耦艺术
- o 通过多态实现开闭原则的典范
- o 理解延迟实例化的核心思想
进阶建议:
- 1. 阅读《设计模式:可复用面向对象软件的基础》工厂方法章节
- 2. 研究Spring框架中BeanFactory的实现源码
- 3. 尝试实现支持泛型的通用工厂接口
- 4. 结合反射技术实现动态工厂
代码练习:
- o 实现一个支持多种日志类型(FileLog、DatabaseLog)的日志工厂系统
- o 扩展汽车工厂案例,增加混合动力汽车类型
掌握工厂方法模式,就如同获得了对象生产的流水线控制权,让代码在复杂的需求变更面前依然保持优雅与灵活。