策略模式是什么
策略模式概述
- 定义:
- 策略模式是一种 行为型设计模式,定义一系列算法(策略),将每个算法封装为独立类,使它们可互换,客户端可动态选择不同策略执行任务。
- 核心思想:
- 将变化的算法与使用场景分离,降低耦合,支持运行时切换。
- 组成:
- 策略接口:定义算法规范。
- 具体策略:实现不同算法。
- 上下文:持有策略引用,执行算法。
核心点
- 策略模式通过封装算法提升灵活性,Spring 中广泛用于动态行为选择。
1. 策略模式核心概念
(1) 角色
- 策略接口(Strategy):
- 定义算法的抽象方法。
- 例:
interface Strategy
。 - 具体策略(Concrete Strategy):
- 实现策略接口,提供具体算法。
- 例:
ConcreteStrategyA
。 - 上下文(Context):
- 持有策略引用,调用算法。
- 例:
Context
。 - 客户端(Client):
- 配置上下文,选择策略。
(2) 优势
- 开闭原则:
- 新增策略无需改上下文。
- 解耦:
- 算法与调用分离。
- 灵活性:
- 运行时动态切换。
(3) 图示
[Client] --> [Context] --> [Strategy]
--> [ConcreteStrategyA]
--> [ConcreteStrategyB]
2. 策略模式实现
(1) 代码示例
- 场景:
- 支付系统支持多种支付方式(支付宝、微信)。
- 代码:
// 策略接口
public interface PaymentStrategy {
void pay(double amount);
}
// 具体策略
public class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("Paying " + amount + " via Alipay");
}
}
public class WechatPayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("Paying " + amount + " via Wechat");
}
}
// 上下文
public class PaymentContext {
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void pay(double amount) {
if (strategy == null) {
throw new IllegalStateException("Strategy not set");
}
strategy.pay(amount);
}
}
// 客户端
public class Client {
public static void main(String[] args) {
PaymentContext context = new PaymentContext();
// 使用支付宝
context.setStrategy(new AlipayStrategy());
context.pay(100.0); // 输出: Paying 100.0 via Alipay
// 切换微信
context.setStrategy(new WechatPayStrategy());
context.pay(200.0); // 输出: Paying 200.0 via Wechat
}
}
(2) 关键点
- 动态切换:
setStrategy
运行时选择算法。- 扩展性:
- 新增支付方式(如银联)只需加
UnionPayStrategy
。 - 封装:
- 每种支付逻辑独立。
3. 策略模式在 Spring 中的应用
- 结合您的问题(Spring AOP、工厂模式):
- Spring 认证:
AuthenticationProvider
使用策略模式。- 例:支持用户名密码、JWT(您提问的单点登录)、OAuth。
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication);
}
@Component
public class UsernamePasswordProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) {
// 用户名密码验证
return new UsernamePasswordAuthenticationToken(principal, credentials);
}
}
@Component
public class JwtProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) {
// JWT 验证
return new JwtAuthenticationToken(token);
}
}
- Spring Security 动态选择
AuthenticationProvider
。 - Spring 资源加载:
ResourceLoader
支持不同协议(file:
、http:
)。- AOP 切面选择:
- 动态选择切面逻辑(如日志、事务)。
- 与工厂模式:
- 策略常与工厂结合,工厂创建策略实例:
@Component
public class PaymentStrategyFactory {
private Map<String, PaymentStrategy> strategies;
@Autowired
public PaymentStrategyFactory(List<PaymentStrategy> strategyList) {
strategies = strategyList.stream()
.collect(Collectors.toMap(s -> s.getClass().getSimpleName(), s -> s));
}
public PaymentStrategy getStrategy(String type) {
return strategies.get(type);
}
}
(4) RESTful API 集成
- 场景:
- API 支持多种序列化格式(JSON、XML)。
- 示例:
public interface Serializer {
String serialize(Object obj);
}
@Component
public class JsonSerializer implements Serializer {
@Override
public String serialize(Object obj) {
return new ObjectMapper().writeValueAsString(obj);
}
}
@RestController
public class UserController {
private Serializer serializer;
@Autowired
public void setSerializer(Serializer serializer) {
this.serializer = serializer;
}
@GetMapping("/users")
public String getUsers() {
User user = new User(1, "Alice");
return serializer.serialize(user);
}
}
4. 使用场景
- 多算法选择:
- 支付方式、排序算法。
- 动态行为:
- 认证方式(JWT、OAuth)。
- 规则引擎:
- 促销规则(满减、折扣)。
- 格式转换:
- 数据序列化(JSON、XML)。
- 事件处理:
- 不同事件触发不同逻辑。
与您的问题
- 单点登录:
- 策略模式实现认证切换(JWT、SAML)。
- Spring AOP:
- 动态选择切面逻辑(如日志策略)。
- RESTful API:
- 序列化或响应处理策略。
- 事务传播:
- 事务管理器选择不同传播行为。
5. 优缺点
优点
- 开闭原则:
- 新增策略无需改上下文。
- 解耦:
- 算法独立,易维护。
- 灵活性:
- 运行时切换策略。
缺点
- 类膨胀:
- 策略多时类数量增加。
- 客户端复杂性:
- 需知道所有策略。
- 初始化开销:
- 动态加载策略需额外逻辑。
6. 策略模式 vs 其他模式
策略 vs 工厂
特性 | 策略模式 | 工厂模式 |
---|---|---|
目的 | 动态选择算法 | 封装对象创建 |
关注 | 行为(算法) | 对象实例 |
结合 | 工厂可创建策略 | 策略不涉及创建 |
策略 vs 状态
- 策略:
- 选择不同算法,外部控制。
- 状态:
- 随状态变化行为,内部切换。
策略 vs 模板方法
- 策略:
- 算法整体替换。
- 模板方法:
- 固定骨架,子类实现步骤。
7. 最佳实践
- 接口清晰:
- 策略接口方法单一职责。
- 结合工厂:
- 用工厂管理策略:
strategy = factory.getStrategy("alipay");
- Spring 注入:
- 用
@Autowired List<Strategy>
自动收集。 - 命名规范:
- 如
JsonSerializer
、AlipayStrategy
。
8. 延伸与面试角度
- 与 Spring:
AuthenticationProvider
、ResourceLoader
是策略模式。- 与工厂:
- 工厂创建策略实例。
- 与 AOP:
- 策略定义切面行为。
- 实际应用:
- 电商:支付、促销策略。
- 微服务:认证、序列化。
- 面试点:
- 问“定义”时,提角色和开闭原则。
- 问“场景”时,提 Spring 和支付示例。
9. 总结
策略模式通过接口封装算法,支持动态切换,适用于支付、认证等场景。Spring 的认证和资源加载广泛使用策略模式。结合您的问题,策略可实现 SSO 认证切换或 API 序列化。面试时,可提代码、Spring 案例或与工厂模式的结合,展示理解深度。
如果您想深入某场景(如 Spring Security 的策略实现)或有具体问题,请告诉我,我可以进一步优化!