核心思想
工厂方法本质是为了解决 **“对象创建” 与 “业务使用” 的强耦合问题 **,并通过 “抽象化” 让系统更灵活、更易扩展
工厂方法模式的核心思路,可以总结为 “定义一个创建对象的抽象接口(工厂接口),让具体的对象创建工作由其子类(具体工厂)完成,业务层只依赖抽象工厂和抽象产品,不依赖具体实现”。
我们可以用一个 “分工比喻” 理解:
- 不使用工厂方法的模式:“厨师(业务层)既要买菜(创建对象),又要做菜(业务逻辑)”;
- 工厂方法模式:“厨师(业务层)只负责做菜,买菜的工作交给专门的‘采购工厂’(具体工厂),厨师只需要告诉工厂‘要什么菜’(抽象产品),不用管‘菜从哪来’(具体实现)”。
代码实现
原始代码实现
在没有使用工厂方法时,我们通常会直接用 new
关键字创建对象,比如一个电商系统中创建 “支付方式” 的场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class OrderService { public void pay(String payType, double amount) { Payment payment; if ("WECHAT".equals(payType)) { payment = new WechatPayment(); } else if ("ALIPAY".equals(payType)) { payment = new AlipayPayment(); } else { throw new RuntimeException("不支持的支付方式"); } payment.processPayment(amount); } }
interface Payment { void processPayment(double amount); } class WechatPayment implements Payment { @Override public void processPayment(double amount) { System.out.println("微信支付:" + amount + "元"); } } class AlipayPayment implements Payment { @Override public void processPayment(double amount) { System.out.println("支付宝支付:" + amount + "元"); } }
|
1 2 3 4 5 6 7 8 9
| public class Client { public static void main(String[] args) { OrderService orderService = new OrderService(); orderService.pay("WECHAT", 3.3); System.out.println("Switching payment ..."); orderService.pay("ALIPAY", 3.3); } }
|
这段代码其实也不会很屎,甚至还知道要抽取通用的逻辑processPayment
来进行处理
但是还是将实际支付逻辑对象的创建,与对象支付逻辑的使用 耦合在了一起
我们可以使用工厂方法设计模式来解决这一问题
最佳实践
“产品抽象化”
定义统一的抽象产品接口(这里的产品、也就是被创建对象的类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public interface Payment { void processPayment(double amount); }
public class AlipayPayment implements Payment{ @Override public void processPayment(double amt) { System.out.println("Paid " + amt + "$ with alipay"); } }
public class WechatPayment implements Payment{ @Override public void processPayment(double amt) { System.out.println("Paid " + amt + "$ with wechat"); } }
|
“工厂抽象化”
定义创建对象的抽象工厂接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public interface PaymentFactory { Payment createPayment(); }
public class AlipayPaymentFactory implements PaymentFactory{ @Override public Payment createPayment() { return new AlipayPayment(); } }
public class WechatPaymentFactory implements PaymentFactory{ @Override public Payment createPayment() { return new WechatPayment(); } }
|
业务层依赖抽象,脱离具体实现
将创建于使用解耦,业务层只负责使用,创建交由工厂的实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class OrderServiceRefactored {
private PaymentFactory paymentFactory;
public OrderServiceRefactored(PaymentFactory paymentFactory) { this.paymentFactory = paymentFactory; }
public void setPaymentFactory(PaymentFactory paymentFactory) { this.paymentFactory = paymentFactory; }
public void payOrder(double amt) { Payment payment = this.paymentFactory.createPayment(); payment.processPayment(amt); }
}
|
模拟客户端测试
由于原先的代码中有根据 payType 枚举参数进行判断的逻辑,而这一段逻辑主要是用来决定对象的创建的
而对象的创建本质上和 OrderService 无关,是 Factory 需要做的事情,因此我们可以将其从 OrderService 中抽离出来
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class PaymentFactorySelector { public static PaymentFactory getFactory(String payType) { if ("WECHAT".equals(payType)) { return new WechatPaymentFactory(); } else if ("ALIPAY".equals(payType)) { return new AlipayPaymentFactory(); } else { throw new IllegalArgumentException("不支持的支付方式: " + payType); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class FactoryMethodClientRefactored {
public static void main(String[] args) { PaymentFactory factory = PaymentFactorySelector.getFactory("WECHAT"); OrderServiceRefactored orderService = new OrderServiceRefactored(factory); orderService.payOrder(3.3);
System.out.println("Switching payment ...");
PaymentFactory alipayFactory = PaymentFactorySelector.getFactory("ALIPAY"); orderService.setPaymentFactory(alipayFactory); orderService.payOrder(3.3); } }
|
总结
工厂方法模式的核心思想,本质是对依赖倒置原则(依赖抽象,不依赖具体)和单一职责原则(一个类只做一件事)的落地,是将业务逻辑类中关联业务逻辑处理对象的创建 与 使用进行解耦
业务类只专注于处理具体业务逻辑,不再进行相关对象的创建
对象的创建统一在工厂接口的实现类中各自决定
简单来说,工厂方法设计模式就是 将对象的创建权交给专门的‘抽象工厂’,业务层只关心‘要什么产品’(通过抽象工厂拿抽象产品),不关心‘产品怎么造’(具体工厂实现),从而实现‘创建’与‘使用’的解耦,让系统易扩展、易维护。