设计模式|策略模式

核心思想

策略模式的核心目的在于:解决 算法 / 行为选择 问题:封装不同的业务逻辑(算法),让逻辑可替换、可扩展

核心角色

通用的抽象策略

是一个接口,定义了不同业务逻辑算法相同的抽象,相同的入参,相同的返回值类型

策略实现类

实现通用的抽象策略接口

策略上下文

选择和使用不同的策略

业务注入

在业务中使用时,通过上下文来选择使用不同策略

代码实践

我们以经典的支付问题为例,原先没有使用设计模式的代码是这样的

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
@Service
public class PaymentService {
// 支付方式常量
public static final String ALIPAY = "alipay";
public static final String WECHAT_PAY = "wechat";

/**
* 统一支付方法(包含所有支付逻辑)
* @param paymentType 支付方式
* @param amount 金额
* @param accountInfo 账户信息(支付宝账号/微信openId/银行卡号)
*/
public void pay(String paymentType, double amount, String accountInfo) {
System.out.println("开始支付...");

// 用大量if-else判断处理不同支付方式
if (ALIPAY.equals(paymentType)) {
// 支付宝支付逻辑
System.out.println("使用支付宝账户 " + accountInfo + " 支付了 " + amount + " 元");
System.out.println("支付宝支付成功!");
} else if (WECHAT_PAY.equals(paymentType)) {
// 微信支付逻辑
System.out.println("使用微信账号 " + accountInfo + " 支付了 " + amount + " 元");
System.out.println("微信支付成功!");
} else {
// 未知支付方式
throw new IllegalArgumentException("不支持的支付方式:" + paymentType);
}
}
}

如果支付方式越来越多,Service中的pay方法就会非常冗长,不好维护并且耦合度太高

我们可以采用策略模式进行重构

策略模式本质上是使用了面向对象中接口的特性

对于上述应用场景,我们可以将【支付】这一个主题抽象一种策略,一个策略具体对应到代码就是一个接口

通用的抽象策略

1
2
3
4
5
6
7
8
9
public interface PaymentStrategy {
/**
* 不同厂商的核心实现逻辑不同,但是出入参都是相同(或是近似)的
* @param amount 支付金额
*/
void pay(double amount);

String getPaymentName();
}

策略实现类

1
2
3
4
5
6
7
8
9
10
11
public class WechatStrategy implements PaymentStrategy{
@Override
public void pay(double amount) {
System.out.println("Successfully pay " + amount + " with " + getPaymentName());
}

@Override
public String getPaymentName() {
return "Wechat Pay";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class AlipayStrategy implements PaymentStrategy{
@Override
public void pay(double amount) {
System.out.println("Alipay login ...");
System.out.println("Successfully pay " + amount + " with " + getPaymentName());
}

@Override
public String getPaymentName() {
return "Alipay";
}
}

策略上下文

1
2
3
4
5
6
7
8
9
10
11
12
public class PaymentContext {
public PaymentStrategy getStrategyByPayType(String payType) {
switch (payType) {
case "WECHAT":
return new WechatStrategy();
case "ALIPAY":
return new AlipayStrategy();
default:
throw new IllegalArgumentException("不支持的支付类型:" + payType);
}
}
}

业务注入

1
2
3
4
5
6
7
8
9
10
11
12
13
public class PaymentService {

private final PaymentContext paymentContext;

public PaymentService(PaymentContext paymentContext) {
this.paymentContext = paymentContext;
}

public void pay(String payType, double amount) {
PaymentStrategy strategy = this.paymentContext.getStrategyByPayType(payType);
strategy.pay(amount);
}
}

模拟调用Service的客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
public class StrategyTest {
public static void main(String[] args) {

PaymentContext context = new PaymentContext();
PaymentService service = new PaymentService(context);

service.doPay("WECHAT", 2.3);

System.out.println("-----");

service.doPay("ALIPAY", 2.3);
}
}

总结

和工厂方法模式的区别

策略模式和工厂方法设计模式的核心区别在于应用的场景(也就是设计的目的)完全不同

  • 策略模式关注的是:将算法/业务逻辑进行封装抽象
  • 工厂方法模式关注的是:将业务对象的创建过程进行封装,使用方只关注业务使用,工厂只关注业务对象的创建

当核心需求是逻辑选择而非对象创建,且 对象创建相关的业务逻辑足够简单时,无需额外引入工厂方法模式,直接用策略模式即可满足需求


设计模式|策略模式
http://example.com/2025/09/02/设计模式-策略模式/
作者
Noctis64
发布于
2025年9月2日
许可协议