1. 工厂方法模式的核心价值解析
工厂方法模式(Factory Method Pattern)作为创建型设计模式的代表,其核心价值在于解耦对象的创建与使用过程。在实际开发中,我经常遇到这样的场景:客户端代码需要创建某个对象,但具体创建哪种子类对象需要在运行时才能确定。如果直接在客户端通过new关键字实例化具体类,会导致代码高度耦合且难以扩展。
重要提示:工厂方法模式最典型的应用场景是当系统需要支持多种同类对象创建,且这些对象具有相同接口但不同实现时。
以支付系统开发为例,我们可能需要支持微信支付、支付宝支付、银联支付等多种支付方式。如果直接在业务代码中实例化具体支付类,代码会变成这样:
java复制// 反面示例:直接依赖具体实现类
if(payType.equals("wechat")){
payment = new WechatPayment();
}else if(payType.equals("alipay")){
payment = new AlipayPayment();
}
这种写法存在三个明显问题:
- 违反开闭原则:新增支付方式需要修改客户端代码
- 业务逻辑与对象创建耦合
- 难以进行单元测试
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 工厂方法模式的经典实现
2.1 UML类图解析
标准的工厂方法模式包含以下核心组件:
- Product(抽象产品):定义产品的接口
- ConcreteProduct(具体产品):实现抽象产品接口的具体类
- Creator(抽象工厂):声明工厂方法
- ConcreteCreator(具体工厂):实现工厂方法,返回具体产品实例
java复制// 抽象产品
interface Payment {
void pay(BigDecimal amount);
}
// 具体产品
class WechatPayment implements Payment {
@Override
public void pay(BigDecimal amount) {
// 微信支付实现
}
}
// 抽象工厂
interface PaymentFactory {
Payment createPayment();
}
// 具体工厂
class WechatPaymentFactory implements PaymentFactory {
@Override
public Payment createPayment() {
return new WechatPayment();
}
}
2.2 Spring框架中的典型应用
在Spring框架中,BeanFactory就是工厂方法模式的完美体现。当我们调用getBean()方法时,Spring会根据配置决定返回哪个具体的Bean实例。这种设计使得:
- 客户端代码只需依赖Bean接口
- 具体实现类的创建由Spring容器负责
- 可以通过配置文件灵活切换实现类
java复制// Spring配置示例
@Configuration
public class PaymentConfig {
@Bean
@ConditionalOnProperty(name="payment.type", havingValue="wechat")
public Payment wechatPayment() {
return new WechatPayment();
}
@Bean
@ConditionalOnProperty(name="payment.type", havingValue="alipay")
public Payment alipayPayment() {
return new AlipayPayment();
}
}
3. 复杂场景下的进阶应用
3.1 参数化工厂方法
当创建逻辑需要根据输入参数变化时,可以扩展基础工厂方法模式:
java复制public class PaymentFactory {
public static Payment createPayment(String type) {
switch(type) {
case "wechat":
return new WechatPayment();
case "alipay":
return new AlipayPayment();
default:
throw new IllegalArgumentException("Unsupported payment type");
}
}
}
注意事项:这种简单工厂虽然实用,但严格来说不属于标准的工厂方法模式,因为它不是通过子类化来改变创建行为。
3.2 配合策略模式使用
在实际项目中,我经常将工厂方法模式与策略模式结合使用:
java复制public class PaymentContext {
private PaymentStrategy strategy;
public PaymentContext(PaymentFactory factory) {
this.strategy = factory.createPayment();
}
public void executePayment(BigDecimal amount) {
strategy.pay(amount);
}
}
这种组合的优点是:
- 创建逻辑与业务逻辑完全分离
- 可以灵活替换支付策略
- 便于单元测试
4. 实战中的经验与陷阱
4.1 性能优化技巧
在高并发场景下,工厂创建对象的性能可能成为瓶颈。我总结了几点优化经验:
- 对于无状态对象,可以使用对象池技术
- 考虑将工厂类设计为单例
- 对创建过程进行缓存优化
java复制public class CachedPaymentFactory {
private static final Map<String, Payment> cache = new ConcurrentHashMap<>();
public Payment createPayment(String type) {
return cache.computeIfAbsent(type, key -> {
switch(key) {
case "wechat": return new WechatPayment();
case "alipay": return new AlipayPayment();
default: throw new IllegalArgumentException();
}
});
}
}
4.2 常见问题排查
-
循环依赖问题:
- 当工厂A依赖产品B,而产品B的工厂又依赖产品A时
- 解决方案:引入三级缓存(Spring的做法)或调整设计
-
类型转换异常:
- 确保工厂返回的类型与客户端期望的类型匹配
- 可以使用泛型进行约束:
java复制interface PaymentFactory<T extends Payment> {
T createPayment();
}
- 初始化性能问题:
- 避免在工厂方法中执行耗时操作
- 考虑使用懒加载模式
5. 现代Java框架中的新形态
5.1 Spring Boot自动配置
Spring Boot的自动配置机制本质上是工厂方法模式的升级版:
java复制@Configuration
@ConditionalOnClass(WechatPayment.class)
public class WechatAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Payment wechatPayment() {
return new WechatPayment();
}
}
这种设计实现了:
- 按需创建Bean
- 自动发现和注册
- 条件化配置
5.2 Lambda表达式简化
Java 8以后,可以使用Lambda表达式简化简单工厂的实现:
java复制public class PaymentFactory {
private static final Map<String, Supplier<Payment>> creators = Map.of(
"wechat", WechatPayment::new,
"alipay", AlipayPayment::new
);
public Payment create(String type) {
Supplier<Payment> creator = creators.get(type);
if(creator == null) throw new IllegalArgumentException();
return creator.get();
}
}
6. 设计模式组合实战案例
在开发电商平台订单系统时,我采用了工厂方法模式与责任链模式的组合:
java复制public interface OrderHandler {
void handle(Order order);
OrderHandler setNext(OrderHandler next);
}
public abstract class AbstractOrderHandlerFactory {
public abstract OrderHandler createHandler();
public OrderHandler createChain(OrderHandler... handlers) {
for(int i=0; i<handlers.length-1; i++) {
handlers[i].setNext(handlers[i+1]);
}
return handlers[0];
}
}
// 使用示例
OrderHandler chain = factory.createChain(
factory.createValidationHandler(),
factory.createPaymentHandler(),
factory.createShippingHandler()
);
chain.handle(order);
这种设计带来了以下好处:
- 每个处理环节可以独立变化
- 处理链的组装逻辑集中在工厂中
- 新增处理环节不影响现有代码
7. 测试策略与Mock技巧
对工厂方法模式的正确测试应该包含两个层面:
7.1 工厂类测试
java复制@Test
void testWechatPaymentFactory() {
PaymentFactory factory = new WechatPaymentFactory();
Payment payment = factory.createPayment();
assertTrue(payment instanceof WechatPayment);
}
7.2 产品类测试
使用Mock框架模拟工厂行为:
java复制@Test
void testPaymentService() {
PaymentFactory mockFactory = mock(PaymentFactory.class);
when(mockFactory.createPayment()).thenReturn(new MockPayment());
PaymentService service = new PaymentService(mockFactory);
service.processPayment(new BigDecimal("100.00"));
verify(mockFactory).createPayment();
}
测试技巧:对于复杂工厂,可以使用参数化测试(JUnit 5):
java复制@ParameterizedTest
@MethodSource("paymentTypes")
void testPaymentCreation(String type, Class<?> expectedClass) {
Payment payment = PaymentFactory.createPayment(type);
assertTrue(expectedClass.isInstance(payment));
}
private static Stream<Arguments> paymentTypes() {
return Stream.of(
Arguments.of("wechat", WechatPayment.class),
Arguments.of("alipay", AlipayPayment.class)
);
}
8. 架构层面的思考
在微服务架构中,工厂方法模式可以演化为服务工厂的概念。例如在Spring Cloud中:
java复制@FeignClient(name = "payment-service", fallbackFactory = PaymentClientFallbackFactory.class)
public interface PaymentClient {
@PostMapping("/pay")
PaymentResponse pay(@RequestBody PaymentRequest request);
}
@Component
public class PaymentClientFallbackFactory implements FallbackFactory<PaymentClient> {
@Override
public PaymentClient create(Throwable cause) {
return new PaymentClientFallback(cause);
}
}
这种模式实现了:
- 服务客户端的动态创建
- 熔断降级处理
- 异常情况的统一封装
在DDD领域驱动设计中,工厂方法模式常用于领域对象的创建:
java复制public interface OrderFactory {
Order createOrder(Customer customer, List<OrderItem> items);
}
public class DefaultOrderFactory implements OrderFactory {
@Override
public Order createOrder(Customer customer, List<OrderItem> items) {
Order order = new Order();
order.setCustomer(customer);
order.setItems(items);
order.setStatus(OrderStatus.CREATED);
order.setCreatedAt(LocalDateTime.now());
return order;
}
}
这种设计确保了:
- 复杂领域对象的创建逻辑集中管理
- 保持领域模型的纯净性
- 易于维护和演进
