这道题其实是 面试中非常经典的面向对象设计题。面试官通过这道题主要考察三个能力:
1️⃣ 是否理解 面向对象设计( OOP ) 2️⃣ 是否掌握 设计模式 3️⃣ 是否能写出 可扩展的系统代码
下面我从 场景 → 问题 → 设计 → 策略模式 → 工厂模式 → 最终代码结构 一步一步讲清楚。
一、题目场景:动态选择支付方式
假设你在开发一个电商系统。
用户支付时可以选择:
- 支付宝
- 微信
- 银行卡
- Apple Pay
- 未来可能增加更多支付方式
用户请求:
POST /pay
{
orderId: 123,
payType: "ALIPAY"
}
系统需要:
根据 payType 调用不同支付逻辑
例如:
ALIPAY -> AliPayService
WECHAT -> WechatPayService
BANK -> BankPayService
二、最差的写法(很多人第一反应)
很多人会写:
if(payType.equals("ALIPAY")){
aliPay();
}else if(payType.equals("WECHAT")){
wechatPay();
}else if(payType.equals("BANK")){
bankPay();
}
问题:
❌ 违反 开闭原则
如果新增支付方式:
ApplePay
就要改代码:
if else +1
如果支付方式越来越多:
100种支付
代码会变成:
巨型 if else
维护灾难。
三、正确思路:使用策略模式
核心思想:
不同的算法/行为封装成不同类,在运行时选择。
支付方式就是不同 支付策略。
四、策略模式结构
策略模式结构:
PaymentStrategy
↑
┌─────────┼─────────┐
AliPay WechatPay BankPay
每种支付方式都是一个 策略实现类。
第一步:定义支付接口
public interface PaymentStrategy {
void pay(Order order);
}
第二步:实现不同支付策略
支付宝:
public class AliPay implements PaymentStrategy {
@Override
public void pay(Order order) {
System.out.println("支付宝支付");
}
}
微信:
public class WechatPay implements PaymentStrategy {
@Override
public void pay(Order order) {
System.out.println("微信支付");
}
}
银行卡:
public class BankPay implements PaymentStrategy {
@Override
public void pay(Order order) {
System.out.println("银行卡支付");
}
}
五、如何动态选择策略?
问题来了:
用户选择支付方式时,如何找到对应策略?
例如:
payType = "ALIPAY"
如何拿到:
AliPay
这时候就需要:
工厂模式
六、工厂模式
工厂模式作用:
负责创建对象,而不是业务代码自己 new。
也就是:
PaymentFactory
负责:
返回对应的支付策略
工厂实现
public class PaymentFactory {
private static Map<String, PaymentStrategy> strategyMap = new HashMap<>();
static {
strategyMap.put("ALIPAY", new AliPay());
strategyMap.put("WECHAT", new WechatPay());
strategyMap.put("BANK", new BankPay());
}
public static PaymentStrategy getStrategy(String payType) {
return strategyMap.get(payType);
}
}
七、业务调用流程
业务代码:
public class PaymentService {
public void pay(String payType, Order order) {
PaymentStrategy strategy = PaymentFactory.getStrategy(payType);
strategy.pay(order);
}
}
执行流程:
用户选择支付方式
↓
PaymentFactory
↓
获取策略对象
↓
执行支付逻辑
八、完整结构
系统结构:
PaymentStrategy
↑
┌────┼─────┐
AliPay WechatPay BankPay
PaymentFactory
PaymentService
职责:
| 组件 | 职责 |
|---|---|
| PaymentStrategy | 定义支付接口 |
| AliPay | 具体策略 |
| WechatPay | 具体策略 |
| PaymentFactory | 创建策略 |
| PaymentService | 业务调用 |
九、为什么这是好设计?
优点:
1 开闭原则
新增支付方式:
ApplePay
只需要:
新增类
不用修改旧代码。
2 解耦
业务代码:
PaymentService
不需要知道:
AliPay
WechatPay
具体实现。
3 可扩展
未来可以扩展:
风控
日志
限流
十、面试回答模板
如果面试再问这题,可以这样回答:
我会使用策略模式封装不同的支付方式,每种支付方式实现统一的支付接口,例如 AliPay、WechatPay。
然后使用工厂模式根据用户选择的 payType 返回对应策略对象,业务代码只需要调用 strategy.pay()。
这样设计可以避免大量 if-else,提高系统扩展性。
十一、面试官真正考察什么
这道题考察的是:
OOP设计
设计模式
系统扩展能力
代码结构
很多大厂面试都会追问的升级版问题:
如果支付方式有 100种,工厂里
map.put()会不会很难维护?
这个问题的答案其实涉及 Spring + 自动注册策略模式,也是很多大厂喜欢问的设计题。
这是一个 非常经典的大厂追问问题,很多面试官在你回答完 策略模式 + 工厂模式 后都会继续问:
如果支付方式有 100种,工厂里
map.put()会不会很难维护?
答案是:是的,会很难维护。
原因是你的代码会变成这样:
static {
strategyMap.put("ALIPAY", new AliPay());
strategyMap.put("WECHAT", new WechatPay());
strategyMap.put("BANK", new BankPay());
strategyMap.put("APPLEPAY", new ApplePay());
strategyMap.put("UNIONPAY", new UnionPay());
...
}
如果有 100种支付方式:
- 工厂类会非常大
- 每新增一种支付方式都要 修改工厂代码
- 违反 开闭原则 ( Open-Closed Principle )
所以需要一种更好的设计:
新增策略类
↓
系统自动注册
↓
无需修改工厂
这就是常见的 自动注册策略模式。
一、优化目标
我们希望达到:
新增支付方式
↓
只新增一个类
↓
系统自动识别
不需要:
修改工厂类
二、解决方案:使用 Spring 自动注入(最常见)
在 Spring 项目中可以利用 IOC 容器。
Spring 可以自动把所有实现类注入到 Map 里。
第一步:定义策略接口
public interface PaymentStrategy {
String getPayType();
void pay(Order order);
}
第二步:实现策略
支付宝:
@Component
public class AliPayStrategy implements PaymentStrategy {
@Override
public String getPayType() {
return "ALIPAY";
}
@Override
public void pay(Order order) {
System.out.println("支付宝支付");
}
}
微信:
@Component
public class WechatPayStrategy implements PaymentStrategy {
@Override
public String getPayType() {
return "WECHAT";
}
@Override
public void pay(Order order) {
System.out.println("微信支付");
}
}
第三步:自动收集策略
@Service
public class PaymentService {
private Map<String, PaymentStrategy> strategyMap = new HashMap<>();
@Autowired
public PaymentService(List<PaymentStrategy> strategies) {
for (PaymentStrategy strategy : strategies) {
strategyMap.put(strategy.getPayType(), strategy);
}
}
public void pay(String payType, Order order) {
PaymentStrategy strategy = strategyMap.get(payType);
strategy.pay(order);
}
}
Spring 会自动把:
AliPayStrategy
WechatPayStrategy
BankPayStrategy
...
全部注入进来。
三、结构图
系统结构变成:
PaymentStrategy
↑
┌─────┼─────┬─────┐
AliPay WechatPay BankPay ...
Spring IOC
↓
List<PaymentStrategy>
↓
Map<String,Strategy>
四、这样有什么好处
1 新增支付方式零修改
新增:
@Component
class ApplePayStrategy implements PaymentStrategy
系统自动识别。
不需要改:
PaymentService
2 符合开闭原则
系统:
对扩展开放
对修改关闭
3 工厂逻辑消失
Spring 已经替代了 工厂模式。
五、面试回答模板
如果面试官问:
如果有100种支付方式,工厂类会不会很难维护?
你可以这样回答:
如果支付方式很多,直接在工厂类中
map.put()会导致代码难维护,并且违反开闭原则。在实际项目中可以使用 Spring 的依赖注入机制,将所有
PaymentStrategy的实现类自动注入为一个List或Map,然后在初始化时动态构建策略映射。这样新增支付方式时只需要新增一个策略类即可,无需修改原有代码。
这就是 比较标准的大厂回答。
六、面试官真正想听什么
这道追问本质是考察:
开闭原则
IOC
Spring自动装配
可扩展架构
如果你能说出:
Spring自动注入策略
基本会 明显加分。