文章目录
- 前言:策略模式在现代架构中的重要性
- 一、策略模式核心概念回顾
-
- [1.1 什么是策略模式?](#1.1 什么是策略模式?)
- [1.2 策略模式的优势](#1.2 策略模式的优势)
- 二、实战案例:支付系统中的策略模式实现
-
- [2.1 完整代码架构](#2.1 完整代码架构)
-
- [2.1.1 枚举定义:支付类型标识](#2.1.1 枚举定义:支付类型标识)
- [2.1.2 策略接口定义](#2.1.2 策略接口定义)
- [2.1.3 具体策略实现](#2.1.3 具体策略实现)
- [2.1.4 策略工厂/注册中心](#2.1.4 策略工厂/注册中心)
- [2.1.5 控制器层](#2.1.5 控制器层)
- [2.2 配置与扩展](#2.2 配置与扩展)
- 三、深度剖析:策略模式+枚举的类加载机制
-
- [3.1 面试热点:类加载全过程解析](#3.1 面试热点:类加载全过程解析)
-
- [3.1.1 JVM层面的类加载(底层机制)](#3.1.1 JVM层面的类加载(底层机制))
- [3.1.2 Spring容器的Bean加载(应用层)](#3.1.2 Spring容器的Bean加载(应用层))
- [3.2 Spring 3.0+ 特性:List自动注入](#3.2 Spring 3.0+ 特性:List自动注入)
- 四、高级特性与扩展
-
- [4.1 策略的优先级和排序](#4.1 策略的优先级和排序)
- [4.2 策略的懒加载和条件化](#4.2 策略的懒加载和条件化)
- [4.3 策略的监控和管理](#4.3 策略的监控和管理)
- 五、性能优化与最佳实践
-
- [5.1 性能优化技巧](#5.1 性能优化技巧)
- [5.2 最佳实践总结](#5.2 最佳实践总结)
- 六、常见面试题深度解析
-
- [6.1 高频面试题集锦](#6.1 高频面试题集锦)
- 七、实际应用场景扩展
-
- [7.1 电商平台中的策略应用](#7.1 电商平台中的策略应用)
- [7.2 风控系统中的策略应用](#7.2 风控系统中的策略应用)
- 总结
前言:策略模式在现代架构中的重要性
在当今微服务和云原生架构盛行的时代,设计模式不再仅仅是教科书中的理论知识,而是成为构建可维护、可扩展系统的必备武器。策略模式作为行为型模式的代表,因其出色的解耦能力和运行时动态切换特性,在支付系统、风控引擎、规则引擎等复杂业务场景中得到广泛应用。
本文将深入剖析策略模式+枚举+Spring DI的组合拳,从底层类加载机制到实战应用,为你呈现一份既有理论深度又有实践价值的完整指南。
一、策略模式核心概念回顾
1.1 什么是策略模式?
策略模式(Strategy Pattern)定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端。
核心组件:
- 策略接口(Strategy):定义算法的公共接口
- 具体策略(Concrete Strategy):实现策略接口的具体算法
- 上下文(Context):持有一个策略对象的引用,负责与具体策略的交互
1.2 策略模式的优势
java
// 传统if-else的硬编码方式(不推荐)
public void pay(int payType, double amount) {
if (payType == 1) {
// 支付宝支付逻辑
} else if (payType == 2) {
// 微信支付逻辑
} else if (payType == 3) {
// 银联支付逻辑
}
// 新增支付方式需要修改此处代码,违反开闭原则
}
// 策略模式实现(推荐)
public void pay(PayEnum payType, double amount) {
PaymentStrategy strategy = factory.getStrategy(payType);
strategy.pay(amount); // 算法与调用者解耦
}
二、实战案例:支付系统中的策略模式实现
2.1 完整代码架构
让我们通过一个完整的支付系统案例,深入理解策略模式的实现细节:
2.1.1 枚举定义:支付类型标识
java
/**
* 支付类型枚举
* 使用枚举而非常量,提供类型安全和更好的可读性
*/
public enum PayEnum {
WXPAY(1, "微信支付"),
ALIPAY(2, "支付宝"),
UNIONPAY(3, "银联支付");
private final int code;
private final String desc;
PayEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
/**
* 根据code获取枚举实例
* 时间复杂度O(n),枚举值少时性能可接受
* 可优化:使用静态Map缓存,实现O(1)查找
*/
public static PayEnum fromCode(int code) {
for (PayEnum pay : PayEnum.values()) {
if (pay.getCode() == code) {
return pay;
}
}
throw new IllegalArgumentException("无效的支付类型编码: " + code);
}
/**
* 优化版本:使用静态Map提升查找性能
*/
private static final Map<Integer, PayEnum> CODE_MAP;
static {
Map<Integer, PayEnum> map = new HashMap<>();
for (PayEnum pay : PayEnum.values()) {
map.put(pay.getCode(), pay);
}
CODE_MAP = Collections.unmodifiableMap(map);
}
public static PayEnum fromCodeFast(int code) {
PayEnum pay = CODE_MAP.get(code);
if (pay == null) {
throw new IllegalArgumentException("无效的支付类型编码: " + code);
}
return pay;
}
}
2.1.2 策略接口定义
java
/**
* 支付策略接口
* 策略模式的核心:定义算法的统一接口
*/
public interface PaymentStrategy {
/**
* 支付方法
* @param amount 支付金额
* @return 支付结果
*/
PayResult pay(double amount);
/**
* 获取策略标识
* 用于策略注册和查找
*/
PayEnum getStrategyCode();
/**
* 策略是否支持当前业务场景
* 可扩展为更复杂的路由逻辑
*/
default boolean isSupported(PaymentContext context) {
return true;
}
}
/**
* 支付结果封装类
*/
@Data
@AllArgsConstructor
public class PayResult {
private boolean success;
private String transactionId;
private String message;
private LocalDateTime payTime;
}
/**
* 支付上下文信息
*/
@Data
public class PaymentContext {
private String orderId;
private Long userId;
private String ipAddress;
private String deviceType;
private Map<String, Object> extraParams;
}
2.1.3 具体策略实现
java
/**
* 微信支付策略
* @Service注解使其成为Spring管理的Bean
*/
@Service
@Slf4j
public class WeChatPayStrategy implements PaymentStrategy {
@Autowired
private WeChatPayClient weChatPayClient;
@Autowired
private PaymentRecordMapper paymentRecordMapper;
@Override
public PayResult pay(double amount) {
log.info("开始微信支付,金额:{}", amount);
try {
// 1. 调用微信支付API
WeChatPayResponse response = weChatPayClient.createPayment(amount);
// 2. 记录支付流水
PaymentRecord record = new PaymentRecord();
record.setPayType(PayEnum.WXPAY.getCode());
record.setAmount(amount);
record.setTransactionId(response.getTransactionId());
record.setStatus(PaymentStatus.PROCESSING.getCode());
paymentRecordMapper.insert(record);
// 3. 返回支付结果
return new PayResult(
true,
response.getTransactionId(),
"微信支付成功",
LocalDateTime.now()
);
} catch (Exception e) {
log.error("微信支付失败", e);
return new PayResult(false, null, "微信支付失败:" + e.getMessage(), LocalDateTime.now());
}
}
@Override
public PayEnum getStrategyCode() {
return PayEnum.WXPAY;
}
@Override
public boolean isSupported(PaymentContext context) {
// 微信支付不支持PC端的某些场景
return !"PC".equals(context.getDeviceType())
|| !context.getExtraParams().containsKey("special_scene");
}
}
/**
* 支付宝策略
*/
@Service
@Slf4j
public class AlipayStrategy implements PaymentStrategy {
@Value("${alipay.app-id}")
private String appId;
@Override
public PayResult pay(double amount) {
log.info("开始支付宝支付,金额:{},AppID:{}", amount, appId);
// 支付宝支付实现逻辑
return new PayResult(true, UUID.randomUUID().toString(),
"支付宝支付成功", LocalDateTime.now());
}
@Override
public PayEnum getStrategyCode() {
return PayEnum.ALIPAY;
}
}
2.1.4 策略工厂/注册中心
java
/**
* 支付策略工厂/注册中心
* 核心职责:管理和分发策略
*
* 这不是传统意义的工厂,而是策略的注册中心和路由中心
*/
@Service
@Slf4j
public class PaymentStrategyRegistry {
/**
* 策略映射表
* 使用ConcurrentHashMap保证线程安全
* key: 支付类型枚举
* value: 对应的策略实现
*/
private final ConcurrentHashMap<PayEnum, PaymentStrategy> strategyMap =
new ConcurrentHashMap<>();
/**
* 所有可用策略列表
* 用于需要遍历所有策略的场景
*/
private final List<PaymentStrategy> allStrategies = new CopyOnWriteArrayList<>();
/**
* 构造函数注入所有PaymentStrategy实现
* Spring 3.0+ 特性:自动注入接口的所有实现
*/
@Autowired
public PaymentStrategyRegistry(List<PaymentStrategy> strategies) {
log.info("开始初始化支付策略注册中心,发现{}个策略实现", strategies.size());
strategies.forEach(strategy -> {
PayEnum strategyCode = strategy.getStrategyCode();
// 防止重复注册
if (strategyMap.containsKey(strategyCode)) {
log.warn("支付策略重复注册:{},已存在的实现:{},新的实现:{}",
strategyCode,
strategyMap.get(strategyCode).getClass().getName(),
strategy.getClass().getName());
}
strategyMap.put(strategyCode, strategy);
allStrategies.add(strategy);
log.info("注册支付策略:{} -> {}", strategyCode, strategy.getClass().getSimpleName());
});
log.info("支付策略注册完成,共计{}个策略", strategyMap.size());
}
/**
* 获取支付策略
* @param payEnum 支付类型
* @return 对应的策略实现
* @throws PaymentStrategyNotFoundException 策略不存在时抛出异常
*/
public PaymentStrategy getStrategy(PayEnum payEnum) {
PaymentStrategy strategy = strategyMap.get(payEnum);
if (strategy == null) {
log.error("未找到对应的支付策略:{}", payEnum);
throw new PaymentStrategyNotFoundException("不支持的支付类型:" + payEnum.getDesc());
}
return strategy;
}
/**
* 根据上下文智能选择策略
* 支持复杂的路由逻辑
*/
public PaymentStrategy selectStrategy(PaymentContext context) {
// 1. 首先尝试根据指定类型获取
if (context.getExtraParams() != null &&
context.getExtraParams().containsKey("pay_type")) {
Integer payTypeCode = (Integer) context.getExtraParams().get("pay_type");
try {
PayEnum payEnum = PayEnum.fromCode(payTypeCode);
PaymentStrategy strategy = getStrategy(payEnum);
if (strategy.isSupported(context)) {
return strategy;
}
} catch (IllegalArgumentException e) {
log.warn("指定的支付类型无效:{}", payTypeCode);
}
}
// 2. 遍历所有策略,选择支持的策略
for (PaymentStrategy strategy : allStrategies) {
if (strategy.isSupported(context)) {
return strategy;
}
}
throw new PaymentStrategyNotFoundException("没有找到适合当前上下文的支付策略");
}
/**
* 动态注册策略(支持热部署)
*/
public void registerStrategy(PayEnum payEnum, PaymentStrategy strategy) {
strategyMap.put(payEnum, strategy);
allStrategies.add(strategy);
log.info("动态注册支付策略:{} -> {}", payEnum, strategy.getClass().getSimpleName());
}
/**
* 获取所有策略(用于监控和管理)
*/
public Map<PayEnum, String> getAllStrategies() {
return strategyMap.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().getClass().getSimpleName()
));
}
}
2.1.5 控制器层
java
/**
* 支付控制器
* 对外提供支付API接口
*/
@RestController
@RequestMapping("/api/payment")
@Slf4j
@Validated
public class PaymentController {
@Autowired
private PaymentStrategyRegistry strategyRegistry;
/**
* 统一支付接口
* @param request 支付请求
* @return 支付结果
*/
@PostMapping("/pay")
public ApiResponse<PayResult> pay(@Valid @RequestBody PaymentRequest request) {
log.info("收到支付请求:{}", request);
try {
// 1. 参数校验和转换
PayEnum payEnum = PayEnum.fromCode(request.getPayType());
// 2. 构建支付上下文
PaymentContext context = new PaymentContext();
context.setOrderId(request.getOrderId());
context.setUserId(request.getUserId());
context.setDeviceType(request.getDeviceType());
context.setExtraParams(request.getExtraParams());
// 3. 获取支付策略(支持智能路由)
PaymentStrategy strategy = strategyRegistry.selectStrategy(context);
// 4. 执行支付
PayResult result = strategy.pay(request.getAmount());
// 5. 返回结果
return ApiResponse.success(result);
} catch (IllegalArgumentException e) {
log.error("支付参数错误", e);
return ApiResponse.error(ErrorCode.PARAM_ERROR, e.getMessage());
} catch (PaymentStrategyNotFoundException e) {
log.error("支付策略未找到", e);
return ApiResponse.error(ErrorCode.PAYMENT_TYPE_NOT_SUPPORTED, e.getMessage());
} catch (Exception e) {
log.error("支付处理异常", e);
return ApiResponse.error(ErrorCode.SYSTEM_ERROR, "支付处理失败");
}
}
/**
* 获取支持的支付方式
*/
@GetMapping("/supported-methods")
public ApiResponse<Map<PayEnum, String>> getSupportedMethods(
@RequestParam(required = false) String deviceType) {
PaymentContext context = new PaymentContext();
context.setDeviceType(deviceType);
Map<PayEnum, String> supportedMethods = new LinkedHashMap<>();
for (PaymentStrategy strategy : strategyRegistry.getAllStrategies()) {
if (strategy.isSupported(context)) {
supportedMethods.put(strategy.getStrategyCode(),
strategy.getStrategyCode().getDesc());
}
}
return ApiResponse.success(supportedMethods);
}
}
/**
* 支付请求DTO
*/
@Data
public class PaymentRequest {
@NotNull(message = "支付类型不能为空")
@Min(value = 1, message = "支付类型无效")
@Max(value = 3, message = "支付类型无效")
private Integer payType;
@NotNull(message = "支付金额不能为空")
@DecimalMin(value = "0.01", message = "支付金额必须大于0")
private Double amount;
@NotBlank(message = "订单号不能为空")
private String orderId;
private Long userId;
private String deviceType;
private Map<String, Object> extraParams;
}
2.2 配置与扩展
yaml
# application.yml
payment:
strategies:
wechat:
enabled: true
app-id: wx1234567890
mch-id: 1234567890
alipay:
enabled: true
app-id: 2019091767145012
unionpay:
enabled: true
java
/**
* 策略配置类
* 支持动态启用/禁用策略
*/
@Configuration
@ConfigurationProperties(prefix = "payment.strategies")
@Data
public class PaymentStrategyConfig {
private WeChatConfig wechat;
private AlipayConfig alipay;
private UnionpayConfig unionpay;
@Bean
@ConditionalOnProperty(name = "payment.strategies.wechat.enabled", havingValue = "true")
public WeChatPayStrategy weChatPayStrategy() {
return new WeChatPayStrategy();
}
@Bean
@ConditionalOnProperty(name = "payment.strategies.alipay.enabled", havingValue = "true")
public AlipayStrategy alipayStrategy() {
return new AlipayStrategy();
}
}
三、深度剖析:策略模式+枚举的类加载机制
3.1 面试热点:类加载全过程解析
面试官提问:"在策略模式+枚举的实现中,JVM和Spring是如何进行类加载的?请详细描述整个过程。"
3.1.1 JVM层面的类加载(底层机制)
java
/**
* JVM类加载的三个阶段:
* 1. Loading(加载)
* 2. Linking(链接)
* 3. Initialization(初始化)
*/
// 以PayEnum为例,详细类加载过程:
public enum PayEnum {
// 阶段1:Loading - 类加载器加载PayEnum.class
// 阶段2:Linking - 验证、准备、解析
// 阶段3:Initialization - 初始化静态字段和枚举实例
WXPAY(1), // 创建PayEnum$1实例(匿名子类)
ALIPAY(2), // 创建PayEnum$2实例
UNIONPAY(3); // 创建PayEnum$3实例
// 枚举的类加载特性:
// 1. 线程安全:JVM保证枚举类只初始化一次
// 2. 防止反射攻击:枚举构造器是私有的
// 3. 序列化安全:枚举有特殊的序列化机制
}
3.1.2 Spring容器的Bean加载(应用层)
java
// Spring容器启动时的Bean加载顺序:
// 步骤1:组件扫描
// Spring扫描到所有带有@Component、@Service注解的类
// 步骤2:Bean实例化(按依赖顺序)
// 2.1 实例化PaymentStrategy实现类(无依赖,最先创建)
// new WeChatPayStrategy()
// new AlipayStrategy()
// new UnionPayStrategy()
// 步骤3:依赖注入
// 3.1 注入PaymentStrategyRegistry的依赖
// Spring收集所有PaymentStrategy实现 → List<PaymentStrategy>
// 3.2 执行PaymentStrategyRegistry构造函数
// strategies.forEach() → 注册到ConcurrentHashMap
// 步骤4:完成所有Bean的初始化
// 此时所有策略已注册完毕,可以使用
/**
* 关键点:
* 1. 策略Bean的创建是无序的,但最终都会被收集到List中
* 2. 使用@DependsOn可以控制Bean的创建顺序
* 3. 循环依赖问题需要特别注意
*/
3.2 Spring 3.0+ 特性:List自动注入
面试官提问:"Spring是如何自动收集接口的所有实现的?请说明其原理。"
java
@Service
public class PaymentStrategyRegistry {
/**
* Spring 3.0+ 的新特性:
* 当构造函数或字段需要List<InterfaceType>时,
* Spring会自动注入该接口的所有实现Bean
*
* 原理:
* 1. Spring在创建Bean时,会分析其依赖
* 2. 发现需要List<PaymentStrategy>
* 3. 从ApplicationContext中获取所有PaymentStrategy类型的Bean
* 4. 按@Order注解排序(如果有)
* 5. 注入到List中
*/
@Autowired
public PaymentStrategyRegistry(List<PaymentStrategy> strategies) {
// 自动注入所有PaymentStrategy实现
// 支持@Order注解指定顺序
}
/**
* 替代方案1:使用ApplicationContext
*/
@Autowired
private ApplicationContext applicationContext;
public void initStrategies() {
Map<String, PaymentStrategy> beans =
applicationContext.getBeansOfType(PaymentStrategy.class);
}
/**
* 替代方案2:使用ObjectProvider(推荐)
* 支持懒加载和可选依赖
*/
@Autowired
private ObjectProvider<PaymentStrategy> strategyProvider;
public List<PaymentStrategy> getStrategies() {
return strategyProvider.stream().collect(Collectors.toList());
}
}
四、高级特性与扩展
4.1 策略的优先级和排序
java
/**
* 带优先级的策略接口
*/
public interface PriorityPaymentStrategy extends PaymentStrategy {
/**
* 获取策略优先级
* @return 优先级数值,越小优先级越高
*/
int getPriority();
/**
* 是否支持兜底
*/
default boolean isFallback() {
return false;
}
}
/**
* 支持排序的策略注册中心
*/
@Service
public class PriorityPaymentRegistry {
private final List<PriorityPaymentStrategy> sortedStrategies;
private final Map<PayEnum, PriorityPaymentStrategy> strategyMap;
@Autowired
public PriorityPaymentRegistry(List<PriorityPaymentStrategy> strategies) {
// 按优先级排序
this.sortedStrategies = strategies.stream()
.sorted(Comparator.comparingInt(PriorityPaymentStrategy::getPriority))
.collect(Collectors.toList());
// 注册到Map
this.strategyMap = sortedStrategies.stream()
.collect(Collectors.toMap(
PriorityPaymentStrategy::getStrategyCode,
Function.identity(),
(existing, replacement) -> {
// 处理重复注册,保留优先级高的
return existing.getPriority() <= replacement.getPriority()
? existing : replacement;
}
));
}
}
4.2 策略的懒加载和条件化
java
/**
* 懒加载策略工厂
* 只有使用时才初始化策略
*/
@Service
@Lazy
public class LazyPaymentStrategyFactory {
@Autowired
private ApplicationContext context;
private final ConcurrentHashMap<PayEnum, PaymentStrategy> cache =
new ConcurrentHashMap<>();
public PaymentStrategy getStrategy(PayEnum payEnum) {
return cache.computeIfAbsent(payEnum, key -> {
// 按需创建策略实例
String beanName = getBeanName(payEnum);
return context.getBean(beanName, PaymentStrategy.class);
});
}
private String getBeanName(PayEnum payEnum) {
switch (payEnum) {
case WXPAY: return "weChatPayStrategy";
case ALIPAY: return "alipayStrategy";
case UNIONPAY: return "unionPayStrategy";
default: throw new IllegalArgumentException("未知的支付类型");
}
}
}
4.3 策略的监控和管理
java
/**
* 策略执行监控
*/
@Aspect
@Component
@Slf4j
public class StrategyExecutionMonitor {
@Pointcut("execution(* com.example.payment.strategy.PaymentStrategy.pay(..))")
public void strategyExecution() {}
@Around("strategyExecution()")
public Object monitorExecution(ProceedingJoinPoint joinPoint) throws Throwable {
String strategyName = joinPoint.getTarget().getClass().getSimpleName();
double amount = (double) joinPoint.getArgs()[0];
long startTime = System.currentTimeMillis();
try {
log.info("策略[{}]开始执行,金额:{}", strategyName, amount);
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - startTime;
log.info("策略[{}]执行成功,耗时:{}ms", strategyName, duration);
// 记录监控指标
Metrics.recordStrategyExecution(strategyName, duration, true);
return result;
} catch (Exception e) {
long duration = System.currentTimeMillis() - startTime;
log.error("策略[{}]执行失败,耗时:{}ms", strategyName, duration, e);
Metrics.recordStrategyExecution(strategyName, duration, false);
throw e;
}
}
}
五、性能优化与最佳实践
5.1 性能优化技巧
java
public class OptimizedPaymentRegistry {
// 1. 使用EnumMap代替ConcurrentHashMap(枚举场景专用)
private final EnumMap<PayEnum, PaymentStrategy> enumMap =
new EnumMap<>(PayEnum.class);
// 2. 缓存策略查找结果
private final ConcurrentHashMap<PaymentContext, PaymentStrategy> contextCache =
new ConcurrentHashMap<>();
// 3. 使用快速失败机制
private final Set<PayEnum> disabledStrategies = ConcurrentHashMap.newKeySet();
public PaymentStrategy getStrategyWithCache(PaymentContext context) {
return contextCache.computeIfAbsent(context, ctx -> {
// 缓存未命中时的查找逻辑
return selectStrategyInternal(ctx);
});
}
// 4. 并行初始化策略
@PostConstruct
public void parallelInit() {
ForkJoinPool customThreadPool = new ForkJoinPool(4);
try {
customThreadPool.submit(() -> {
strategies.parallelStream().forEach(strategy -> {
PayEnum code = strategy.getStrategyCode();
enumMap.put(code, strategy);
});
}).get();
} catch (InterruptedException | ExecutionException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("策略初始化失败", e);
}
}
}
5.2 最佳实践总结
-
接口设计原则
- 保持策略接口的单一职责
- 使用默认方法减少重复代码
- 合理设计策略标识
-
注册中心设计
- 支持动态注册和注销
- 提供策略的监控和管理接口
- 实现策略的版本管理
-
异常处理
- 定义策略相关的业务异常
- 实现优雅的降级机制
- 提供详细的错误信息
-
测试策略
- 对每个策略进行单元测试
- 测试策略之间的切换逻辑
- 集成测试整个策略体系
六、常见面试题深度解析
6.1 高频面试题集锦
Q1:策略模式和工厂模式有什么区别?
java
// 策略模式:关注行为的封装和替换
// 工厂模式:关注对象的创建
// 示例对比:
// 工厂模式:根据类型创建不同的支付对象
Payment payment = PaymentFactory.create(payType);
// 策略模式:根据类型选择不同的支付算法
PaymentStrategy strategy = strategyRegistry.getStrategy(payType);
strategy.pay(amount);
Q2:为什么要在策略模式中使用枚举?
- 类型安全:编译时检查,避免魔法数字
- 代码可读性:枚举名称有语义,易于理解
- 扩展性:新增策略只需添加枚举值
- 与Switch完美结合:支持switch语句
Q3:如何处理策略模式中的循环依赖?
java
// 解决方案1:使用Setter注入代替构造器注入
@Service
public class PaymentStrategyRegistry {
private List<PaymentStrategy> strategies;
@Autowired
public void setStrategies(List<PaymentStrategy> strategies) {
this.strategies = strategies;
}
}
// 解决方案2:使用@Lazy延迟加载
@Service
public class WeChatPayStrategy implements PaymentStrategy {
@Lazy
@Autowired
private PaymentStrategyRegistry registry;
}
Q4:如何实现策略的热插拔?
java
// 实现策略的动态注册和注销
public class DynamicStrategyRegistry {
private final Map<PayEnum, PaymentStrategy> strategyMap =
new ConcurrentHashMap<>();
// 动态注册
public void registerStrategy(PayEnum type, PaymentStrategy strategy) {
strategyMap.put(type, strategy);
// 发布策略变更事件
applicationContext.publishEvent(new StrategyChangedEvent(this, type, "REGISTER"));
}
// 动态注销
public void unregisterStrategy(PayEnum type) {
strategyMap.remove(type);
applicationContext.publishEvent(new StrategyChangedEvent(this, type, "UNREGISTER"));
}
}
Q5:大型系统中策略模式如何分层?
java
// 分层架构示例:
// 第一层:基础策略层(支付、退款、查询)
interface BasePaymentStrategy {
PayResult pay(PaymentRequest request);
}
// 第二层:业务策略层(组合基础策略)
interface BusinessPaymentStrategy extends BasePaymentStrategy {
boolean supportSplitPayment();
PayResult splitPay(SplitPaymentRequest request);
}
// 第三层:路由策略层(智能路由)
interface RoutingStrategy {
BasePaymentStrategy selectStrategy(PaymentContext context);
}
// 第四层:监控策略层(监控和治理)
interface MonitoringStrategy {
void monitor(StrategyExecution execution);
}
七、实际应用场景扩展
7.1 电商平台中的策略应用
java
/**
* 电商平台中的多种策略组合
*/
public class EcommerceStrategyApplication {
// 1. 价格计算策略
interface PricingStrategy {
BigDecimal calculatePrice(Order order);
}
// 2. 运费计算策略
interface ShippingStrategy {
BigDecimal calculateShipping(Address address, List<Product> products);
}
// 3. 优惠券策略
interface CouponStrategy {
DiscountResult applyCoupon(Order order, Coupon coupon);
}
// 4. 库存扣减策略
interface InventoryStrategy {
InventoryResult deductInventory(Order order);
}
}
7.2 风控系统中的策略应用
java
/**
* 风控策略引擎
*/
public class RiskControlStrategyEngine {
// 风险检查策略链
@Service
public class RiskCheckChain {
@Autowired
private List<RiskCheckStrategy> riskChecks;
public RiskCheckResult check(PaymentRequest request) {
RiskCheckResult result = new RiskCheckResult();
for (RiskCheckStrategy check : riskChecks) {
if (!check.isEnabled()) continue;
RiskCheckResult checkResult = check.check(request);
result.merge(checkResult);
if (result.isBlocked()) {
break; // 风险检查链中断
}
}
return result;
}
}
// 风险检查策略接口
interface RiskCheckStrategy {
boolean isEnabled();
RiskCheckResult check(PaymentRequest request);
int getOrder(); // 执行顺序
}
// 具体风险检查策略
@Service
@Order(1)
public class IPRiskCheck implements RiskCheckStrategy {
@Override
public RiskCheckResult check(PaymentRequest request) {
// IP风险检查逻辑
}
}
}
总结
通过本文的深入剖析,我们全面掌握了策略模式与枚举在Spring Boot中的高级应用。从基础的实现到高级的特性扩展,从性能优化到面试题解析,我们构建了一个完整的策略模式知识体系。
关键收获:
- 策略模式的核心是行为的封装和动态替换
- 枚举提供了类型安全和良好的可读性
- Spring的自动注入机制极大简化了策略管理
- 合理的架构设计需要考虑性能、扩展性和可维护性
未来展望:
随着云原生和Serverless架构的发展,策略模式将更多地与函数式编程、事件驱动架构结合,形成更灵活、更高效的解决方案。
如需获取更多关于创建型模式(单例、工厂、建造者等)、结构型模式(代理、适配器、装饰者等)、行为型模式(策略、观察者、模板方法等)的深度解析、应用场景与实战案例,请持续关注本专栏《设计模式精讲与实战》系列文章。我们将继续深入探讨设计模式在现代架构中的最佳实践,助你构建更优雅、更健壮的软件系统。