工厂模式(Factory Pattern):掌控对象创建的艺术
✨ 模式简介
工厂模式是一种创建型设计模式,它定义了一个创建对象的接口,但将具体实例化的工作推迟到子类。
就像现实中的工厂生产产品一样,它把new
操作封装起来,让代码更加灵活可扩展。
📦 应用场景
- 需要创建多种相似对象(如不同数据库连接)
- 对象创建过程复杂(需要多步初始化)
- 需要统一管理对象生命周期
- 希望隐藏具体实现类(如JDBC驱动加载)
- Spring框架的
BeanFactory
- 日志框架的
LoggerFactory
🧠 核心实现思路
- 定义产品接口(抽象产品)
- 创建具体产品类
- 定义工厂接口(抽象工厂)
- 实现具体工厂类
- 客户端通过工厂获取对象,而非直接
new
🧱 工厂模式的多种实现方式
1. 简单工厂(静态工厂)
public class PizzaFactory {
public static Pizza createPizza(String type) {
switch (type) {
case "cheese": return new CheesePizza();
case "pepperoni": return new PepperoniPizza();
default: throw new IllegalArgumentException("Unknown pizza type");
}
}
}
✅ 优点:实现简单
❌ 缺点:违反开闭原则,新增类型需修改工厂
2. 工厂方法模式(推荐)
public interface PizzaFactory {
Pizza createPizza();
}
public class NYPizzaFactory implements PizzaFactory {
@Override
public Pizza createPizza() {
return new NYStyleCheesePizza();
}
}
✅ 优点:符合开闭原则,扩展性强
❌ 缺点:类数量增加
3. 抽象工厂模式(产品族)
public interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
public class WinFactory implements GUIFactory {
@Override
public Button createButton() {
return new WinButton();
}
// 其他产品创建方法...
}
✅ 优点:能创建相关对象族
❌ 缺点:系统复杂度高
💎 最佳实现推荐
静态工厂 + 注册表(Spring风格)
public class BeanFactory {
private static final Map<String, Supplier<Object>> registry = new HashMap<>();
static {
registry.put("userService", UserService::new);
registry.put("orderService", OrderService::new);
}
public static Object getBean(String name) {
return registry.get(name).get();
}
}
枚举工厂(线程安全)
public enum LoggerFactory {
FILE {
public Logger create() { return new FileLogger(); }
},
CONSOLE {
public Logger create() { return new ConsoleLogger(); }
};
public abstract Logger create();
}
💣 常见问题与解决方案
问题1:如何避免工厂类膨胀?
✅ 解决方案:
使用Map
维护创建逻辑,如Spring的BeanDefinitionRegistry
问题2:如何支持动态扩展?
✅ 解决方案:
结合SPI机制(ServiceLoader)或反射
问题3:循环依赖如何处理?
✅ 解决方案:
-
使用三级缓存(参考Spring)
-
改为Setter注入
📊 模式对比
模式类型 | 灵活性 (1-3★) |
复杂度 (1-3★) |
适用场景 |
---|---|---|---|
简单工厂 | ⭐⭐☆ | ⭐☆☆ | 固定类型少量变化 |
工厂方法 | ⭐⭐⭐ | ⭐⭐☆ | 需要扩展的子类体系 |
抽象工厂 | ⭐⭐⭐ | ⭐⭐⭐ | 相关产品族创建 |
📚 实际应用案例
- JDBC中的工厂模式
Connection conn = DriverManager.getConnection(url);
// DriverManager就是连接工厂
- Spring框架
@Bean
public DataSource dataSource() {
return new HikariDataSource(); // 数据源工厂
}
- Java集合框架
List<String> list = Collections.unmodifiableList(originalList);
// Collections是集合装饰器的工厂
🎯 总结建议
-
优先选择:工厂方法模式(符合开闭原则)
-
性能考量:对高频创建对象使用对象池
-
框架整合:Spring中优先使用
@Bean
注解 -
避免滥用:简单对象直接
new
更清晰 -
设计原则:依赖抽象(工厂接口),而非具体实现