意图:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。
策略模式是消除 if-else 的利器,也是后端业务代码中最实用的模式。
UML 简述:定义策略接口和多个实现,Context 持有策略引用,通过替换不同策略来改变行为。
经典示例:支付策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public interface PaymentStrategy { boolean pay(BigDecimal amount); }
@Component("ALIPAY") public class AlipayPayment implements PaymentStrategy { }
@Component("WECHAT") public class WechatPayment implements PaymentStrategy { }
@Service public class PaymentService { @Autowired private Map<String, PaymentStrategy> strategyMap;
public boolean pay(String channel, BigDecimal amount) { PaymentStrategy strategy = strategyMap.get(channel); if (strategy == null) throw new IllegalArgumentException("不支持的支付渠道: " + channel); return strategy.pay(amount); } }
|
利用 Spring 的依赖注入,所有 PaymentStrategy 的实现类会自动注入到 Map 中(key 是 Bean 名称)。新增支付渠道只需要加一个类,零修改已有代码 —— 这就是 OCP 的体现。
JDK Comparator —— 策略模式的经典
1 2 3 4 5 6 7 8 9 10 11
| List<User> users = new ArrayList<>();
users.sort(Comparator.comparingInt(User::getAge));
users.sort(Comparator.comparing(User::getName));
users.sort(Comparator.comparing(User::getCreateTime).reversed());
|
Comparator 接口就是策略接口,每次 sort() 调用传入不同的 Lambda 就是不同的策略。
Spring 中的策略模式——Resource 加载
1 2 3 4 5 6 7 8 9 10 11
| ResourceLoader loader = new DefaultResourceLoader();
Resource res1 = loader.getResource("classpath:application.yml");
Resource res2 = loader.getResource("file:/opt/config/app.yml");
Resource res3 = loader.getResource("https://example.com/config.yml");
|
策略模式 vs 工厂模式
| 模式 |
关注点 |
返回 |
| 策略 |
封装可互换的行为/算法 |
通常无返回值,执行操作 |
| 工厂 |
封装可互换的创建逻辑 |
返回创建好的对象 |
两者经常组合使用:工厂负责选择策略,策略负责执行逻辑。支付示例中的 strategyMap.get(channel) 就是最简单的工厂。