一、傳統策略模式的痛點與突破
1.1 傳統策略實現回顧
// 傳統支付策略接口
public interface PaymentStrategy {void pay(BigDecimal amount);
}// 具體策略實現
public class AlipayStrategy implements PaymentStrategy {public void pay(BigDecimal amount) { /* 支付寶支付邏輯 */ }
}// 策略上下文
public class PaymentContext {private PaymentStrategy strategy;public void setStrategy(PaymentStrategy strategy) {this.strategy = strategy;}public void executePayment(BigDecimal amount) {strategy.pay(amount);}
}
存在問題:
? 策略類型固定,無法通用化
? 新增策略需修改上下文類
? 無法動態管理策略集合
二、泛型化策略工具類設計
2.1 核心接口定義
/*** 通用策略接口* @param <T> 策略參數類型* @param <R> 返回結果類型*/
public interface GenericStrategy<T, R> {/*** 是否支持當前策略類型*/boolean support(String strategyType);/*** 執行策略*/R apply(T param);
}
2.2 策略上下文工具類
public class StrategyContext<T, R> {private final Map<String, GenericStrategy<T, R>> strategyMap = new ConcurrentHashMap<>();/*** 注冊策略*/public void registerStrategy(String strategyType, GenericStrategy<T, R> strategy) {strategyMap.put(strategyType, strategy);}/*** 執行策略*/public R execute(String strategyType, T param) {GenericStrategy<T, R> strategy = Optional.ofNullable(strategyMap.get(strategyType)).orElseThrow(() -> new IllegalArgumentException("未找到策略: " + strategyType));return strategy.apply(param);}/*** 批量執行策略*/public List<R> executeAll(T param) {return strategyMap.values().stream().map(s -> s.apply(param)).collect(Collectors.toList());}
}
三、Spring集成與自動裝配
3.1 自動注冊策略實現
@Configuration
public class StrategyAutoConfiguration {/*** 自動發現所有策略Bean并注冊*/@Beanpublic <T, R> StrategyContext<T, R> strategyContext(List<GenericStrategy<T, R>> strategies) {StrategyContext<T, R> context = new StrategyContext<>();strategies.forEach(strategy -> context.registerStrategy(strategy.getClass().getAnnotation(StrategyType.class).value(),strategy));return context;}
}/*** 策略類型注解*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface StrategyType {String value();
}
3.2 策略實現示例
@StrategyType("alipay")
@Component
public class AlipayStrategy implements GenericStrategy<PaymentRequest, PaymentResult> {@Overridepublic boolean support(String strategyType) {return "alipay".equals(strategyType);}@Overridepublic PaymentResult apply(PaymentRequest request) {// 支付寶支付具體實現}
}
四、企業級應用案例
4.1 支付策略路由
@RestController
@RequestMapping("/payment")
public class PaymentController {@Autowiredprivate StrategyContext<PaymentRequest, PaymentResult> paymentContext;@PostMapping("/{type}")public PaymentResult pay(@PathVariable String type, @RequestBody PaymentRequest request) {return paymentContext.execute(type, request);}
}
4.2 動態折扣計算
public enum DiscountType {NEW_USER, FESTIVAL, VIP_LEVEL
}public class DiscountStrategy implements GenericStrategy<DiscountType, BigDecimal> {private static final Map<DiscountType, BigDecimal> DISCOUNT_MAP = Map.of(DiscountType.NEW_USER, new BigDecimal("0.9"),DiscountType.FESTIVAL, new BigDecimal("0.8"),DiscountType.VIP_LEVEL, new BigDecimal("0.7"));@Overridepublic boolean support(String strategyType) {return Arrays.stream(DiscountType.values()).anyMatch(e -> e.name().equals(strategyType));}@Overridepublic BigDecimal apply(DiscountType type) {return DISCOUNT_MAP.get(type);}
}
五、高級功能擴展
5.1 策略優先級控制
public class PriorityStrategyContext<T, R> extends StrategyContext<T, R> {private final PriorityQueue<GenericStrategy<T, R>> priorityQueue = new PriorityQueue<>(Comparator.comparingInt(this::getPriority));private int getPriority(GenericStrategy<T, R> strategy) {return strategy.getClass().isAnnotationPresent(StrategyPriority.class) ?strategy.getClass().getAnnotation(StrategyPriority.class).value() : 0;}@Overridepublic void registerStrategy(String type, GenericStrategy<T, R> strategy) {super.registerStrategy(type, strategy);priorityQueue.offer(strategy);}public R executeFirst(T param) {return priorityQueue.peek().apply(param);}
}
5.2 策略執行監控
public class MonitoredStrategyContext<T, R> extends StrategyContext<T, R> {private final MeterRegistry meterRegistry;@Overridepublic R execute(String strategyType, T param) {Timer.Sample sample = Timer.start(meterRegistry);try {R result = super.execute(strategyType, param);sample.stop(meterRegistry.timer("strategy.execute.time", "type", strategyType));return result;} catch (Exception e) {meterRegistry.counter("strategy.error", "type", strategyType).increment();throw e;}}
}
六、最佳實踐總結
-
合理定義策略邊界:每個策略應聚焦單一職責
-
統一異常處理:定義策略執行異常體系
-
版本控制策略:支持多版本策略共存
-
動態配置支持:結合配置中心實現熱更新
-
性能優化:緩存高頻使用策略