1. 工厂模式:对象创建的工业化革命
第一次接触工厂模式是在2013年参与一个电商平台开发时。当时系统需要对接多个物流供应商,每个物流公司的API接口和计费规则都不相同。如果直接在业务代码中new出各个物流服务对象,代码很快就会变成一团乱麻。直到团队中的架构师引入了工厂模式,这个问题才迎刃而解。
工厂模式的核心价值在于:将对象的创建与使用分离。就像现实中的工厂一样,我们不需要知道产品是如何制造的,只需要告诉工厂我们需要什么产品。这种解耦带来的灵活性,在复杂系统中尤为重要。
2. 工厂模式的三种形态
2.1 简单工厂模式
简单工厂是最基础的形式,它通过一个静态方法根据输入参数返回不同的对象实例。虽然不属于GoF 23种设计模式之一,但却是理解工厂模式的绝佳起点。
public class LogisticsFactory { public static LogisticsService createService(String type) { switch(type) { case "SF": return new SFExpressService(); case "JD": return new JDLogisticsService(); case "STO": return new STOExpressService(); default: throw new IllegalArgumentException("未知的物流类型"); } } }注意:简单工厂的缺点在于新增类型时需要修改工厂类,违反了开闭原则。但在类型较少且变化不频繁的场景下,它仍然是个不错的选择。
2.2 工厂方法模式
工厂方法模式通过引入抽象工厂接口,将具体产品的创建延迟到子类中实现。这样新增产品类型时,只需要新增对应的工厂子类即可。
// 抽象工厂 public interface LogisticsFactory { LogisticsService createService(); } // 具体工厂 public class SFExpressFactory implements LogisticsFactory { @Override public LogisticsService createService() { return new SFExpressService(); } }我在一个跨国电商项目中就采用了这种模式。当需要支持新的国家/地区物流时,只需要实现新的工厂类,完全不需要修改现有代码。
2.3 抽象工厂模式
抽象工厂模式用于创建一系列相关或依赖的对象。它比工厂方法更抽象,适合产品族创建的场景。
public interface UIFactory { Button createButton(); Dialog createDialog(); } public class WindowsFactory implements UIFactory { // 实现Windows风格的控件创建 } public class MacOSFactory implements UIFactory { // 实现MacOS风格的控件创建 }在开发跨平台应用时,这种模式特别有用。通过配置不同的工厂实现,可以轻松切换整套UI风格。
3. 工厂模式的实现细节
3.1 对象创建的复杂性封装
工厂模式最直接的价值就是封装了复杂对象的创建过程。比如数据库连接池的创建:
public class ConnectionFactory { public Connection createConnection() { // 1. 读取配置 // 2. 初始化连接池 // 3. 设置超时参数 // 4. 返回包装后的连接对象 return new PooledConnection(...); } }客户端代码只需要调用createConnection(),完全不需要关心背后的复杂逻辑。
3.2 依赖注入的实现基础
现代框架如Spring的核心功能之一依赖注入,本质上就是工厂模式的升级版。通过@Autowired注解,框架自动为我们创建并注入所需对象。
@Service public class OrderService { @Autowired private LogisticsService logisticsService; // 使用logisticsService无需关心其具体实现 }3.3 与单例模式的结合
工厂模式经常与单例模式配合使用,确保某些特殊对象只被创建一次:
public class LoggerFactory { private static Map<String, Logger> instances = new ConcurrentHashMap<>(); public static Logger getLogger(String name) { return instances.computeIfAbsent(name, k -> new FileLogger(name)); } }4. 工厂模式的实战应用
4.1 框架设计中的应用
几乎所有主流框架都大量使用工厂模式:
- Spring的BeanFactory
- Hibernate的SessionFactory
- JDK中的Calendar.getInstance()
以Spring为例,它的BeanFactory是整个IoC容器的核心接口:
public interface BeanFactory { Object getBean(String name) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; // 其他工厂方法... }4.2 业务系统中的应用
在电商系统中,支付方式的处理就很适合用工厂模式:
public interface PaymentService { void pay(BigDecimal amount); } public class PaymentFactory { public static PaymentService createService(PaymentType type) { switch(type) { case ALIPAY: return new AlipayService(); case WECHAT: return new WechatPayService(); case UNION: return new UnionPayService(); default: throw new UnsupportedOperationException(); } } }这样当新增支付方式时,业务逻辑代码几乎不需要修改。
4.3 跨平台开发中的应用
在开发需要支持多平台的SDK时,抽象工厂模式大显身手:
public interface PushNotificationFactory { PushService createPushService(); TokenService createTokenService(); } // Android实现 public class AndroidPushFactory implements PushNotificationFactory { // 实现Android特有的推送服务 } // iOS实现 public class IOSPushFactory implements PushNotificationFactory { // 实现iOS特有的推送服务 }5. 工厂模式的陷阱与最佳实践
5.1 常见陷阱
- 过度设计:简单场景使用抽象工厂会导致代码过于复杂
- 循环依赖:工厂A依赖产品B,工厂B又依赖产品A
- 性能问题:每次创建新对象可能带来开销
5.2 最佳实践
合理选择工厂类型:
- 简单工厂:类型固定且少
- 工厂方法:需要扩展性
- 抽象工厂:处理产品族
结合其他模式:
- 原型模式:缓存并克隆对象
- 建造者模式:复杂对象的逐步构建
使用依赖注入: 现代开发中,优先考虑使用DI框架而非手动实现工厂
// 使用Spring的配置方式 @Configuration public class AppConfig { @Bean @ConditionalOnProperty(name="logistics.type", havingValue="SF") public LogisticsService sfExpressService() { return new SFExpressService(); } }6. 工厂模式的演进与替代方案
6.1 Java 8后的函数式工厂
利用Supplier接口可以更简洁地实现工厂:
Map<String, Supplier<LogisticsService>> factories = new HashMap<>(); factories.put("SF", SFExpressService::new); factories.put("JD", JDLogisticsService::new); LogisticsService service = factories.get(type).get();6.2 服务定位器模式
在某些场景下,服务定位器可以作为工厂的替代方案:
public class ServiceLocator { private static Map<Class<?>, Object> services = new HashMap<>(); public static <T> T getService(Class<T> serviceClass) { return serviceClass.cast(services.get(serviceClass)); } }6.3 现代DI框架的自动装配
Spring等框架通过注解自动完成对象创建和依赖注入:
@Service public class OrderService { @Autowired private PaymentService paymentService; // 无需手动创建paymentService }工厂模式从最初的简单工厂,发展到现在的依赖注入框架,体现了软件设计思想的演进。理解其本质,才能在不同场景下灵活运用。