策略模式

策略模式

1. 策略模式要解决什么问题?

当你的系统有一类业务,输入不同,处理规则不同,但是处理结果一致,策略模式就适合你。

比如,消息通知

  • type=email:走 SMTP
  • type=sms:走短信网关
  • type=webhook:发 HTTP
  • type=ding:钉钉机器人

这个规则可能会不断追加,调整,最简单的方式就是写if-else

1
2
3
4
5
6
7
8
9
10
11
public void notify(String type, String target, String content) {
if ("email".equals(type)) {
// email logic
} else if ("sms".equals(type)) {
// sms logic
} else if ("webhook".equals(type)) {
// webhook logic
} else {
throw new IllegalArgumentException("unknown type");
}
}

分支会越写越长、越来越难改、测试也难拆。

而策略模式就是为了解决这个问题而存在的。

2. 策略模式怎么实现?

策略模式,就是把算法封装起来,让调用者选择使用哪个算法。

2.1 策略模式有以下几个组成元素:

  • 策略接口:定义了算法的抽象,通常由抽象类或抽象方法组成。
  • 策略实现类:实现了策略接口,定义了具体的算法。
  • 上下文:持有策略接口的引用,调用者通过上下文调用策略接口,从而调用具体的算法。
  • 策略工厂:创建策略实现类,并返回给调用者。

2.2 策略模式实现代码

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

[//]: # (请求和返回对象)
import java.util.Map;

public record NotifyRequest(
String target,
String content,
Map<String, Object> extras
) {}

public record NotifyResult(
boolean success,
String message
) {
public static NotifyResult ok(String msg) {
return new NotifyResult(true, msg);
}
public static NotifyResult fail(String msg) {
return new NotifyResult(false, msg);
}
}


public interface NotifyStrategy {

/** 这个策略支持的类型,比如 "email" / "sms" */
String type();

/** 执行投递 */
NotifyResult send(NotifyRequest req);
}

[//]: # (这个是一个策略工厂,用于创建策略实现类)
public class NotifyStrategyRegistry {

private final Map<String, NotifyStrategy> map;

public NotifyStrategyRegistry(List<NotifyStrategy> strategies) {
this.map = strategies.stream()
.collect(Collectors.toUnmodifiableMap(
NotifyStrategy::type,
Function.identity(),
(a, b) -> { throw new IllegalStateException("Duplicate type: " + a.type()); }
));
}

public NotifyStrategy get(String type) {
NotifyStrategy s = map.get(type);
if (s == null) throw new IllegalArgumentException("Unknown type: " + type);
return s;
}
}

[//]: # (具体策略的实现Email)
public class EmailNotifyStrategy implements NotifyStrategy {

@Override
public String type() {
return "email";
}

@Override
public NotifyResult send(NotifyRequest req) {
// 这里假装调用 SMTP 或第三方邮件服务
if (!req.target().contains("@")) {
return NotifyResult.fail("invalid email: " + req.target());
}
System.out.println("[EMAIL] to=" + req.target() + " content=" + req.content());
return NotifyResult.ok("email sent");
}
}
[//]: # (业务 Service)

public class NotifyService {

private final NotifyStrategyRegistry registry;

public NotifyService(NotifyStrategyRegistry registry) {
this.registry = registry;
}

public NotifyResult notify(String type, NotifyRequest req) {
if (req == null) return NotifyResult.fail("request is null");
if (req.target() == null || req.target().isBlank()) return NotifyResult.fail("target is blank");
if (req.content() == null || req.content().isBlank()) return NotifyResult.fail("content is blank");

try {
return registry.get(type).send(req);
} catch (Exception e) {
return NotifyResult.fail("send failed: " + e.getMessage());
}
}
}

现在就可以直接

  • 选择策略:registry.get(type)
  • 执行:send(…)

3. 这个模式带来的好处

  • 消灭一堆 if/else,逻辑更清晰
  • 新增策略不改老代码(符合开闭原则:对扩展开放,对修改关闭)
  • 每个策略可单测,测试粒度更细
  • 更容易做“按配置动态启用策略”

这个暂时就这样了,后续我补上一些图,可能会更明显,敬请期待。


策略模式
https://mazepeng.com/2026/01/05/java/策略模式/
作者
马泽朋
发布于
2026年1月5日
许可协议