一、模式定义与核心思想
1.1 模式定义
策略模式(Strategy Pattern)是一种行为型设计模式,定义一系列算法,将每个算法封装起来,并且使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端。
1.2 核心思想
- 封装变化:将易变的算法部分独立出来
- 面向接口编程:定义策略接口,具体实现可互换
- 组合优于继承:通过组合策略对象,避免继承导致的类爆炸
二、模式结构详解
2.1 UML类图
复制
┌─────────────────┐ ┌─────────────────┐
│ Context │ │ Strategy │
├────────────────-┤ ├────────────────-┤
│ -strategy │<>------->│ +execute():void │
├────────────────-┤ └─────────────────┘
│ +setStrategy() │ ^
│ +execute() │ │
└─────────────────┘ ┌─────────────────────┐
│ │
┌─────────────┴──────┐ ┌────────────┴─────────┐
│ ConcreteStrategyA │ │ ConcreteStrategyB │
├────────────────────-┤ ├──────────────────────┤
│ +execute():void │ │ +execute():void │
└────────────────────-┘ └──────────────────────┘
2.2 核心角色
- Context:上下文,持有策略引用
- Strategy:策略接口
- ConcreteStrategy:具体策略实现
三、Java实现详解
3.1 基础实现框架
java
java
下载
复制
// 1. 策略接口
public interface PaymentStrategy {
/**
* 支付方法
* @param amount 支付金额
* @return 支付结果
*/
PaymentResult pay(BigDecimal amount);
/**
* 获取策略名称
* @return 策略名称
*/
String getStrategyName();
/**
* 是否支持该支付方式
* @return 是否支持
*/
boolean isSupported();
}
// 2. 支付结果类
public class PaymentResult {
private boolean success;
private String transactionId;
private String message;
private LocalDateTime payTime;
private BigDecimal actualAmount;
// 构造器、getter、setter
public PaymentResult(boolean success, String transactionId, String message) {
this.success = success;
this.transactionId = transactionId;
this.message = message;
this.payTime = LocalDateTime.now();
}
// builder模式
public static PaymentResultBuilder builder() {
return new PaymentResultBuilder();
}
public static class PaymentResultBuilder {
private boolean success;
private String transactionId;
private String message;
private BigDecimal actualAmount;
public PaymentResultBuilder success(boolean success) {
this.success = success;
return this;
}
public PaymentResultBuilder transactionId(String transactionId) {
this.transactionId = transactionId;
return this;
}
public PaymentResultBuilder message(String message) {
this.message = message;
return this;
}
public PaymentResultBuilder actualAmount(BigDecimal amount) {
this.actualAmount = amount;
return this;
}
public PaymentResult build() {
PaymentResult result = new PaymentResult(success, transactionId, message);
result.setActualAmount(actualAmount);
return result;
}
}
// getters and setters
// ...
}
3.2 具体策略实现
3.2.1 信用卡支付策略
java
java
下载
复制
public class CreditCardPaymentStrategy implements PaymentStrategy {
private final String cardNumber;
private final String cardHolder;
private final String expiryDate;
private final String cvv;
private final boolean enable3DSecure;
public CreditCardPaymentStrategy(String cardNumber, String cardHolder,
String expiryDate, String cvv) {
this(cardNumber, cardHolder, expiryDate, cvv, true);
}
public CreditCardPaymentStrategy(String cardNumber, String cardHolder,
String expiryDate, String cvv,
boolean enable3DSecure) {
validateCardDetails(cardNumber, expiryDate, cvv);
this.cardNumber = cardNumber;
this.cardHolder = cardHolder;
this.expiryDate = expiryDate;
this.cvv = cvv;
this.enable3DSecure = enable3DSecure;
}
private void validateCardDetails(String cardNumber, String expiryDate, String cvv) {
if (cardNumber == null || !cardNumber.matches("\d{13,19}")) {
throw new IllegalArgumentException("Invalid card number");
}
if (expiryDate == null || !expiryDate.matches("(0[1-9]|1[0-2])/[0-9]{2}")) {
throw new IllegalArgumentException("Invalid expiry date format (MM/YY)");
}
if (cvv == null || !cvv.matches("\d{3,4}")) {
throw new IllegalArgumentException("Invalid CVV");
}
}
@Override
public PaymentResult pay(BigDecimal amount) {
System.out.println("使用信用卡支付: " + cardNumber);
System.out.println("持卡人: " + cardHolder);
System.out.println("支付金额: $" + amount);
// 模拟3D安全验证
if (enable3DSecure) {
System.out.println("进行3D安全验证...");
if (!perform3DSecureVerification()) {
return PaymentResult.builder()
.success(false)
.message("3D Secure验证失败")
.build();
}
}
// 模拟银行API调用
boolean paymentSuccess = processCreditCardPayment(amount);
if (paymentSuccess) {
String transactionId = "CC" + System.currentTimeMillis() +
cardNumber.substring(cardNumber.length() - 4);
return PaymentResult.builder()
.success(true)
.transactionId(transactionId)
.message("信用卡支付成功")
.actualAmount(amount)
.build();
} else {
return PaymentResult.builder()
.success(false)
.message("信用卡支付失败: 余额不足或卡片被拒")
.build();
}
}
private boolean perform3DSecureVerification() {
// 模拟3D安全验证
return Math.random() > 0.1; // 90%成功率
}
private boolean processCreditCardPayment(BigDecimal amount) {
// 模拟银行支付处理
// 实际项目中这里会调用银行API
try {
Thread.sleep(100); // 模拟网络延迟
return Math.random() > 0.2; // 80%成功率
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
@Override
public String getStrategyName() {
return "CREDIT_CARD";
}
@Override
public boolean isSupported() {
// 检查卡片是否在有效期内
LocalDate expiry = parseExpiryDate(expiryDate);
return !expiry.isBefore(LocalDate.now());
}
private LocalDate parseExpiryDate(String expiryDate) {
String[] parts = expiryDate.split("/");
int month = Integer.parseInt(parts[0]);
int year = 2000 + Integer.parseInt(parts[1]);
return LocalDate.of(year, month, 1).withDayOfMonth(
YearMonth.of(year, month).lengthOfMonth()
);
}
}
3.2.2 PayPal支付策略
java
java
下载
复制
public class PayPalPaymentStrategy implements PaymentStrategy {
private final String email;
private final String password;
private String accessToken;
private LocalDateTime tokenExpiryTime;
public PayPalPaymentStrategy(String email, String password) {
this.email = email;
this.password = password;
}
@Override
public PaymentResult pay(BigDecimal amount) {
System.out.println("使用PayPal支付");
System.out.println("PayPal账户: " + email);
// 获取访问令牌
if (!authenticate()) {
return PaymentResult.builder()
.success(false)
.message("PayPal认证失败")
.build();
}
// 检查余额
BigDecimal balance = getPayPalBalance();
if (balance.compareTo(amount) < 0) {
return PaymentResult.builder()
.success(false)
.message("PayPal余额不足,当前余额: $" + balance)
.build();
}
// 执行支付
boolean paymentSuccess = processPayPalPayment(amount);
if (paymentSuccess) {
String transactionId = "PP" + System.currentTimeMillis() +
email.hashCode();
return PaymentResult.builder()
.success(true)
.transactionId(transactionId)
.message("PayPal支付成功")
.actualAmount(amount)
.build();
} else {
return PaymentResult.builder()
.success(false)
.message("PayPal支付失败")
.build();
}
}
private boolean authenticate() {
// 如果令牌有效,直接返回
if (accessToken != null && tokenExpiryTime != null &&
tokenExpiryTime.isAfter(LocalDateTime.now())) {
return true;
}
// 模拟PayPal OAuth认证
System.out.println("正在认证PayPal账户...");
try {
Thread.sleep(200); // 模拟网络延迟
// 模拟认证
if (isValidCredentials(email, password)) {
accessToken = "PP_TOKEN_" + UUID.randomUUID();
tokenExpiryTime = LocalDateTime.now().plusHours(1);
return true;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return false;
}
private boolean isValidCredentials(String email, String password) {
// 简化验证逻辑
return email.contains("@") && password.length() >= 6;
}
private BigDecimal getPayPalBalance() {
// 模拟获取余额
return new BigDecimal("1000.00"); // 模拟固定余额
}
private boolean processPayPalPayment(BigDecimal amount) {
// 模拟PayPal支付处理
try {
Thread.sleep(150);
return Math.random() > 0.15; // 85%成功率
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
@Override
public String getStrategyName() {
return "PAYPAL";
}
@Override
public boolean isSupported() {
// PayPal通常全球支持
return true;
}
}
3.2.3 加密货币支付策略
java
java
下载
复制
public class CryptocurrencyPaymentStrategy implements PaymentStrategy {
private final String walletAddress;
private final CryptoCurrency currency;
private final BigDecimal gasLimit; // Gas限制
private final BigDecimal gasPrice; // Gas价格
public enum CryptoCurrency {
BITCOIN("BTC", "比特币", 6),
ETHEREUM("ETH", "以太坊", 18),
USDT("USDT", "泰达币", 6);
private final String symbol;
private final String name;
private final int decimals;
CryptoCurrency(String symbol, String name, int decimals) {
this.symbol = symbol;
this.name = name;
this.decimals = decimals;
}
public String getSymbol() { return symbol; }
public String getName() { return name; }
public int getDecimals() { return decimals; }
}
public CryptocurrencyPaymentStrategy(String walletAddress, CryptoCurrency currency) {
this(walletAddress, currency,
new BigDecimal("21000"), new BigDecimal("20"));
}
public CryptocurrencyPaymentStrategy(String walletAddress, CryptoCurrency currency,
BigDecimal gasLimit, BigDecimal gasPrice) {
validateWalletAddress(walletAddress, currency);
this.walletAddress = walletAddress;
this.currency = currency;
this.gasLimit = gasLimit;
this.gasPrice = gasPrice;
}
private void validateWalletAddress(String address, CryptoCurrency currency) {
if (address == null || address.trim().isEmpty()) {
throw new IllegalArgumentException("钱包地址不能为空");
}
switch (currency) {
case BITCOIN:
if (!address.matches("^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$")) {
throw new IllegalArgumentException("无效的比特币地址");
}
break;
case ETHEREUM:
if (!address.matches("^0x[a-fA-F0-9]{40}$")) {
throw new IllegalArgumentException("无效的以太坊地址");
}
break;
case USDT:
if (!address.matches("^T[a-zA-Z0-9]{33}$")) {
throw new IllegalArgumentException("无效的USDT地址");
}
break;
}
}
@Override
public PaymentResult pay(BigDecimal amount) {
System.out.println("使用" + currency.getName() + "支付");
System.out.println("钱包地址: " + walletAddress);
System.out.println("支付金额: " + amount + " " + currency.getSymbol());
// 计算矿工费
BigDecimal gasFee = calculateGasFee();
BigDecimal totalAmount = amount.add(gasFee);
System.out.println("矿工费: " + gasFee + " Gwei");
System.out.println("总计: " + totalAmount + " " + currency.getSymbol());
// 检查余额
BigDecimal balance = getWalletBalance();
if (balance.compareTo(totalAmount) < 0) {
return PaymentResult.builder()
.success(false)
.message("余额不足,当前余额: " + balance + " " + currency.getSymbol())
.build();
}
// 构建交易
String transactionHash = buildTransaction(amount, gasFee);
if (transactionHash != null) {
return PaymentResult.builder()
.success(true)
.transactionId(transactionHash)
.message(currency.getName() + "支付成功")
.actualAmount(amount)
.build();
} else {
return PaymentResult.builder()
.success(false)
.message(currency.getName() + "交易失败")
.build();
}
}
private BigDecimal calculateGasFee() {
// 计算矿工费: gasLimit * gasPrice
return gasLimit.multiply(gasPrice)
.divide(new BigDecimal("1000000000")); // 转换为Gwei
}
private BigDecimal getWalletBalance() {
// 模拟获取钱包余额
// 实际项目中会调用区块链API
return new BigDecimal("5.0"); // 5个币
}
private String buildTransaction(BigDecimal amount, BigDecimal gasFee) {
// 模拟构建区块链交易
try {
System.out.println("构建" + currency.getName() + "交易...");
Thread.sleep(500); // 模拟区块链网络延迟
// 模拟交易失败(网络拥堵等)
if (Math.random() < 0.1) {
System.out.println("交易失败: 网络拥堵");
return null;
}
// 生成交易哈希
String hash = "0x" + UUID.randomUUID().toString().replace("-", "");
System.out.println("交易已广播,哈希: " + hash);
System.out.println("等待确认...");
// 模拟区块确认
for (int i = 1; i <= 3; i++) {
Thread.sleep(1000);
System.out.println("第" + i + "个区块确认");
}
return hash;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
}
}
@Override
public String getStrategyName() {
return "CRYPTO_" + currency.getSymbol();
}
@Override
public boolean isSupported() {
// 检查网络连接和钱包状态
return checkNetworkConnection() && checkWalletStatus();
}
private boolean checkNetworkConnection() {
// 模拟网络检查
return Math.random() > 0.2; // 80%网络可用
}
private boolean checkWalletStatus() {
// 模拟钱包状态检查
return true;
}
}
3.3 策略工厂模式
java
java
下载
复制
// 策略工厂
public class PaymentStrategyFactory {
private static final Map<String, PaymentStrategy> strategies = new ConcurrentHashMap<>();
private static final Map<String, StrategyConfig> strategyConfigs = new ConcurrentHashMap<>();
static {
// 加载配置文件中的策略配置
loadStrategyConfigs();
}
public static PaymentStrategy getStrategy(String strategyType,
Map<String, Object> params) {
// 检查缓存
String cacheKey = buildCacheKey(strategyType, params);
if (strategies.containsKey(cacheKey)) {
return strategies.get(cacheKey);
}
PaymentStrategy strategy = createStrategy(strategyType, params);
strategies.put(cacheKey, strategy);
return strategy;
}
private static PaymentStrategy createStrategy(String strategyType,
Map<String, Object> params) {
StrategyConfig config = strategyConfigs.get(strategyType);
if (config == null) {
throw new IllegalArgumentException("不支持的支付策略: " + strategyType);
}
if (!config.isEnabled()) {
throw new IllegalStateException("支付策略已被禁用: " + strategyType);
}
// 验证必填参数
validateRequiredParams(strategyType, params, config.getRequiredParams());
switch (strategyType.toUpperCase()) {
case "CREDIT_CARD":
return new CreditCardPaymentStrategy(
(String) params.get("cardNumber"),
(String) params.get("cardHolder"),
(String) params.get("expiryDate"),
(String) params.get("cvv"),
(Boolean) params.getOrDefault("enable3DSecure", true)
);
case "PAYPAL":
return new PayPalPaymentStrategy(
(String) params.get("email"),
(String) params.get("password")
);
case "CRYPTO_BTC":
return new CryptocurrencyPaymentStrategy(
(String) params.get("walletAddress"),
CryptocurrencyPaymentStrategy.CryptoCurrency.BITCOIN
);
case "CRYPTO_ETH":
return new CryptocurrencyPaymentStrategy(
(String) params.get("walletAddress"),
CryptocurrencyPaymentStrategy.CryptoCurrency.ETHEREUM
);
case "ALIPAY":
return new AlipayPaymentStrategy(
(String) params.get("alipayAccount")
);
case "WECHAT_PAY":
return new WeChatPaymentStrategy(
(String) params.get("openId")
);
default:
throw new IllegalArgumentException("未知支付策略: " + strategyType);
}
}
private static void validateRequiredParams(String strategyType,
Map<String, Object> params,
Set<String> requiredParams) {
for (String param : requiredParams) {
if (!params.containsKey(param) || params.get(param) == null) {
throw new IllegalArgumentException(
"参数 '" + param + "' 是必需的,对于策略: " + strategyType
);
}
}
}
private static String buildCacheKey(String strategyType, Map<String, Object> params) {
StringBuilder key = new StringBuilder(strategyType);
params.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry ->
key.append("_").append(entry.getKey()).append(":").append(entry.getValue())
);
return key.toString();
}
private static void loadStrategyConfigs() {
// 从配置文件或数据库加载策略配置
strategyConfigs.put("CREDIT_CARD",
new StrategyConfig(true,
Set.of("cardNumber", "cardHolder", "expiryDate", "cvv"))
);
strategyConfigs.put("PAYPAL",
new StrategyConfig(true, Set.of("email", "password"))
);
strategyConfigs.put("CRYPTO_BTC",
new StrategyConfig(true, Set.of("walletAddress"))
);
strategyConfigs.put("CRYPTO_ETH",
new StrategyConfig(true, Set.of("walletAddress"))
);
strategyConfigs.put("ALIPAY",
new StrategyConfig(true, Set.of("alipayAccount"))
);
strategyConfigs.put("WECHAT_PAY",
new StrategyConfig(true, Set.of("openId"))
);
}
// 策略配置类
private static class StrategyConfig {
private boolean enabled;
private Set<String> requiredParams;
public StrategyConfig(boolean enabled, Set<String> requiredParams) {
this.enabled = enabled;
this.requiredParams = requiredParams;
}
public boolean isEnabled() { return enabled; }
public Set<String> getRequiredParams() { return requiredParams; }
}
}
3.4 上下文类实现
java
java
下载
复制
// 支付上下文
public class PaymentContext {
private PaymentStrategy paymentStrategy;
private String orderId;
private BigDecimal amount;
private String currency = "CNY";
private PaymentContextState state = PaymentContextState.INITIALIZED;
public enum PaymentContextState {
INITIALIZED,
STRATEGY_SELECTED,
VALIDATING,
PROCESSING,
SUCCESS,
FAILED,
CANCELLED
}
public PaymentContext(String orderId, BigDecimal amount) {
this.orderId = orderId;
this.amount = amount;
}
public PaymentContext(String orderId, BigDecimal amount, String currency) {
this(orderId, amount);
this.currency = currency;
}
public void setPaymentStrategy(PaymentStrategy strategy) {
if (strategy == null) {
throw new IllegalArgumentException("支付策略不能为空");
}
if (!strategy.isSupported()) {
throw new IllegalStateException("支付策略不支持: " + strategy.getStrategyName());
}
this.paymentStrategy = strategy;
this.state = PaymentContextState.STRATEGY_SELECTED;
System.out.println("支付策略已设置: " + strategy.getStrategyName());
}
public PaymentResult executePayment() {
validatePayment();
try {
state = PaymentContextState.PROCESSING;
System.out.println("开始处理订单支付: " + orderId);
System.out.println("支付金额: " + amount + " " + currency);
PaymentResult result = paymentStrategy.pay(amount);
if (result.isSuccess()) {
state = PaymentContextState.SUCCESS;
System.out.println("支付成功! 交易号: " + result.getTransactionId());
} else {
state = PaymentContextState.FAILED;
System.out.println("支付失败: " + result.getMessage());
}
return result;
} catch (Exception e) {
state = PaymentContextState.FAILED;
System.out.println("支付过程异常: " + e.getMessage());
return PaymentResult.builder()
.success(false)
.message("支付异常: " + e.getMessage())
.build();
}
}
private void validatePayment() {
if (state == PaymentContextState.INITIALIZED) {
throw new IllegalStateException("请先设置支付策略");
}
if (paymentStrategy == null) {
throw new IllegalStateException("支付策略未设置");
}
if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("支付金额必须大于0");
}
state = PaymentContextState.VALIDATING;
}
public void cancelPayment() {
if (state == PaymentContextState.SUCCESS) {
throw new IllegalStateException("支付已完成,无法取消");
}
state = PaymentContextState.CANCELLED;
System.out.println("支付已取消: " + orderId);
}
// 支持策略链
public PaymentResult executeWithFallback(List<PaymentStrategy> fallbackStrategies) {
PaymentResult result = null;
List<PaymentStrategy> allStrategies = new ArrayList<>();
allStrategies.add(paymentStrategy);
allStrategies.addAll(fallbackStrategies);
for (PaymentStrategy strategy : allStrategies) {
try {
System.out.println("尝试支付策略: " + strategy.getStrategyName());
setPaymentStrategy(strategy);
result = executePayment();
if (result.isSuccess()) {
break;
}
} catch (Exception e) {
System.out.println("策略 " + strategy.getStrategyName() +
" 执行失败: " + e.getMessage());
}
}
return result != null ? result :
PaymentResult.builder()
.success(false)
.message("所有支付策略都失败")
.build();
}
// Getters
public PaymentContextState getState() { return state; }
public String getOrderId() { return orderId; }
public BigDecimal getAmount() { return amount; }
public String getCurrency() { return currency; }
}
3.5 客户端使用示例
java
java
下载
复制
public class StrategyPatternDemo {
public static void main(String[] args) {
// 示例1: 基础使用
System.out.println("=== 示例1: 基础策略模式使用 ===");
demoBasicStrategy();
// 示例2: 策略工厂使用
System.out.println("\n=== 示例2: 策略工厂使用 ===");
demoStrategyFactory();
// 示例3: 策略链(降级策略)
System.out.println("\n=== 示例3: 策略链(降级策略)===");
demoStrategyChain();
// 示例4: 动态策略切换
System.out.println("\n=== 示例4: 动态策略切换 ===");
demoDynamicStrategySwitching();
}
private static void demoBasicStrategy() {
// 创建支付上下文
PaymentContext context = new PaymentContext("ORDER_001",
new BigDecimal("199.99"), "USD");
// 使用信用卡支付
PaymentStrategy creditCardStrategy = new CreditCardPaymentStrategy(
"4111111111111111",
"JOHN DOE",
"12/28",
"123"
);
context.setPaymentStrategy(creditCardStrategy);
PaymentResult result1 = context.executePayment();
printResult(result1);
// 切换到PayPal支付
System.out.println("\n切换支付方式...");
PaymentStrategy paypalStrategy = new PayPalPaymentStrategy(
"john.doe@example.com",
"password123"
);
// 重新设置上下文金额
context = new PaymentContext("ORDER_002", new BigDecimal("299.99"));
context.setPaymentStrategy(paypalStrategy);
PaymentResult result2 = context.executePayment();
printResult(result2);
}
private static void demoStrategyFactory() {
// 使用策略工厂创建支付策略
Map<String, Object> params = new HashMap<>();
params.put("cardNumber", "5555555555554444");
params.put("cardHolder", "JANE DOE");
params.put("expiryDate", "06/27");
params.put("cvv", "456");
params.put("enable3DSecure", true);
try {
PaymentStrategy strategy = PaymentStrategyFactory.getStrategy("CREDIT_CARD", params);
PaymentContext context = new PaymentContext("ORDER_003",
new BigDecimal("149.99"));
context.setPaymentStrategy(strategy);
PaymentResult result = context.executePayment();
printResult(result);
} catch (Exception e) {
System.err.println("支付失败: " + e.getMessage());
}
}
private static void demoStrategyChain() {
// 准备主策略和降级策略
Map<String, Object> cryptoParams = new HashMap<>();
cryptoParams.put("walletAddress", "0x742d35Cc6634C0532925a3b844Bc454e4438f44e");
PaymentStrategy primaryStrategy = PaymentStrategyFactory.getStrategy(
"CRYPTO_ETH", cryptoParams);
// 准备降级策略
Map<String, Object> creditCardParams = new HashMap<>();
creditCardParams.put("cardNumber", "378282246310005");
creditCardParams.put("cardHolder", "FALLBACK USER");
creditCardParams.put("expiryDate", "08/29");
creditCardParams.put("cvv", "789");
PaymentStrategy fallbackStrategy = PaymentStrategyFactory.getStrategy(
"CREDIT_CARD", creditCardParams);
// 执行带降级的支付
PaymentContext context = new PaymentContext("ORDER_004",
new BigDecimal("99.99"));
context.setPaymentStrategy(primaryStrategy);
List<PaymentStrategy> fallbacks = Collections.singletonList(fallbackStrategy);
PaymentResult result = context.executeWithFallback(fallbacks);
printResult(result);
}
private static void demoDynamicStrategySwitching() {
// 模拟动态策略切换场景
System.out.println("模拟智能支付路由系统...");
PaymentContext context = new PaymentContext("ORDER_005",
new BigDecimal("89.99"));
// 根据不同的条件选择策略
String userCountry = "CN";
BigDecimal amount = context.getAmount();
String timeOfDay = LocalTime.now().getHour() < 12 ? "MORNING" : "AFTERNOON";
PaymentStrategy selectedStrategy = null;
if ("CN".equals(userCountry)) {
if (amount.compareTo(new BigDecimal("1000")) < 0) {
// 小额支付使用微信支付
Map<String, Object> wechatParams = new HashMap<>();
wechatParams.put("openId", "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o");
selectedStrategy = PaymentStrategyFactory.getStrategy(
"WECHAT_PAY", wechatParams);
} else {
// 大额支付使用支付宝
Map<String, Object> alipayParams = new HashMap<>();
alipayParams.put("alipayAccount", "zhangsan@alipay.com");
selectedStrategy = PaymentStrategyFactory.getStrategy(
"ALIPAY", alipayParams);
}
} else if ("US".equals(userCountry)) {
if ("MORNING".equals(timeOfDay)) {
// 早上使用PayPal
Map<String, Object> paypalParams = new HashMap<>();
paypalParams.put("email", "user@example.com");
paypalParams.put("password", "password123");
selectedStrategy = PaymentStrategyFactory.getStrategy(
"PAYPAL", paypalParams);
} else {
// 其他时间使用信用卡
Map<String, Object> creditCardParams = new HashMap<>();
creditCardParams.put("cardNumber", "4111111111111111");
creditCardParams.put("cardHolder", "JOHN DOE");
creditCardParams.put("expiryDate", "12/28");
creditCardParams.put("cvv", "123");
selectedStrategy = PaymentStrategyFactory.getStrategy(
"CREDIT_CARD", creditCardParams);
}
}
if (selectedStrategy != null) {
context.setPaymentStrategy(selectedStrategy);
PaymentResult result = context.executePayment();
printResult(result);
} else {
System.out.println("没有找到合适的支付策略");
}
}
private static void printResult(PaymentResult result) {
System.out.println("\n支付结果:");
System.out.println("成功: " + result.isSuccess());
System.out.println("交易号: " + result.getTransactionId());
System.out.println("消息: " + result.getMessage());
System.out.println("时间: " + result.getPayTime());
if (result.getActualAmount() != null) {
System.out.println("实际金额: " + result.getActualAmount());
}
}
}
四、高级应用:策略模式组合模式
java
java
下载
复制
// 复合策略:组合多个策略形成策略链
public class CompositePaymentStrategy implements PaymentStrategy {
private final List<PaymentStrategy> strategies;
private final CompositeStrategyMode mode;
public enum CompositeStrategyMode {
FALLBACK, // 降级模式:按顺序尝试,直到成功
SPLIT, // 拆分模式:金额拆分到多个策略
PARALLEL // 并行模式:同时尝试多个策略
}
public CompositePaymentStrategy(List<PaymentStrategy> strategies,
CompositeStrategyMode mode) {
this.strategies = new ArrayList<>(strategies);
this.mode = mode;
}
@Override
public PaymentResult pay(BigDecimal amount) {
switch (mode) {
case FALLBACK:
return executeFallback(amount);
case SPLIT:
return executeSplit(amount);
case PARALLEL:
return executeParallel(amount);
default:
throw new IllegalStateException("未知的组合策略模式: " + mode);
}
}
private PaymentResult executeFallback(BigDecimal amount) {
for (PaymentStrategy strategy : strategies) {
if (!strategy.isSupported()) {
continue;
}
System.out.println("尝试策略: " + strategy.getStrategyName());
PaymentResult result = strategy.pay(amount);
if (result.isSuccess()) {
return PaymentResult.builder()
.success(true)
.transactionId(result.getTransactionId())
.message("组合支付成功(降级模式),最终策略: " +
strategy.getStrategyName())
.actualAmount(amount)
.build();
}
}
return PaymentResult.builder()
.success(false)
.message("所有降级策略都失败")
.build();
}
private PaymentResult executeSplit(BigDecimal amount) {
if (strategies.isEmpty()) {
throw new IllegalStateException("拆分支付至少需要一个策略");
}
// 将金额平均拆分
BigDecimal splitAmount = amount.divide(
new BigDecimal(strategies.size()), 2, RoundingMode.HALF_UP);
List<PaymentResult> results = new ArrayList<>();
int successCount = 0;
for (int i = 0; i < strategies.size(); i++) {
PaymentStrategy strategy = strategies.get(i);
BigDecimal currentAmount = (i == strategies.size() - 1) ?
amount.subtract(splitAmount.multiply(new BigDecimal(strategies.size() - 1))) :
splitAmount;
System.out.println("策略" + (i+1) + "(" + strategy.getStrategyName() +
")支付金额: " + currentAmount);
PaymentResult result = strategy.pay(currentAmount);
results.add(result);
if (result.isSuccess()) {
successCount++;
} else {
// 如果有任何一个失败,尝试回滚成功的
rollbackSuccessfulPayments(results, i);
return PaymentResult.builder()
.success(false)
.message("拆分支付失败,策略" + strategy.getStrategyName() +
"支付失败: " + result.getMessage())
.build();
}
}
return PaymentResult.builder()
.success(true)
.transactionId("SPLIT_" + System.currentTimeMillis())
.message("拆分支付成功,使用了" + successCount + "个策略")
.actualAmount(amount)
.build();
}
private PaymentResult executeParallel(BigDecimal amount) {
// 简化实现:实际需要处理线程安全
ExecutorService executor = Executors.newFixedThreadPool(strategies.size());
List<Future<PaymentResult>> futures = new ArrayList<>();
for (PaymentStrategy strategy : strategies) {
Callable<PaymentResult> task = () -> strategy.pay(amount);
futures.add(executor.submit(task));
}
executor.shutdown();
try {
// 等待第一个成功的
for (Future<PaymentResult> future : futures) {
try {
PaymentResult result = future.get(10, TimeUnit.SECONDS);
if (result.isSuccess()) {
// 取消其他任务
for (Future<PaymentResult> f : futures) {
if (!f.isDone()) {
f.cancel(true);
}
}
return result;
}
} catch (Exception e) {
// 继续尝试下一个
}
}
} catch (Exception e) {
Thread.currentThread().interrupt();
}
return PaymentResult.builder()
.success(false)
.message("并行支付全部失败")
.build();
}
private void rollbackSuccessfulPayments(List<PaymentResult> results, int currentIndex) {
// 实现回滚逻辑
for (int i = 0; i < currentIndex; i++) {
PaymentResult result = results.get(i);
if (result.isSuccess()) {
System.out.println("回滚策略" + (i+1) + "的支付: " +
result.getTransactionId());
// 实际回滚逻辑...
}
}
}
@Override
public String getStrategyName() {
return "COMPOSITE_" + mode;
}
@Override
public boolean isSupported() {
return strategies.stream().anyMatch(PaymentStrategy::isSupported);
}
}
五、应用场景深度分析
5.1 支付系统(如前所示)
5.2 排序算法策略
java
java
下载
复制
// 排序策略接口
public interface SortStrategy<T extends Comparable<T>> {
List<T> sort(List<T> items);
String getName();
SortPerformance analyzePerformance(List<T> items);
}
// 性能分析类
class SortPerformance {
private final long timeMillis;
private final long memoryUsed;
private final int comparisons;
public SortPerformance(long timeMillis, long memoryUsed, int comparisons) {
this.timeMillis = timeMillis;
this.memoryUsed = memoryUsed;
this.comparisons = comparisons;
}
// getters...
}
// 具体排序策略
public class QuickSortStrategy<T extends Comparable<T>> implements SortStrategy<T> {
@Override
public List<T> sort(List<T> items) {
List<T> sorted = new ArrayList<>(items);
quickSort(sorted, 0, sorted.size() - 1);
return sorted;
}
private void quickSort(List<T> items, int low, int high) {
if (low < high) {
int pi = partition(items, low, high);
quickSort(items, low, pi - 1);
quickSort(items, pi + 1, high);
}
}
private int partition(List<T> items, int low, int high) {
T pivot = items.get(high);
int i = low - 1;
for (int j = low; j < high; j++) {
if (items.get(j).compareTo(pivot) <= 0) {
i++;
Collections.swap(items, i, j);
}
}
Collections.swap(items, i + 1, high);
return i + 1;
}
@Override
public String getName() {
return "快速排序";
}
@Override
public SortPerformance analyzePerformance(List<T> items) {
long startTime = System.nanoTime();
long startMemory = Runtime.getRuntime().totalMemory() -
Runtime.getRuntime().freeMemory();
List<T> sorted = sort(items);
long endTime = System.nanoTime();
long endMemory = Runtime.getRuntime().totalMemory() -
Runtime.getRuntime().freeMemory();
return new SortPerformance(
(endTime - startTime) / 1_000_000,
endMemory - startMemory,
estimateComparisons(items.size())
);
}
private int estimateComparisons(int n) {
return (int) (n * Math.log(n) / Math.log(2));
}
}
// 排序上下文
public class SortContext<T extends Comparable<T>> {
private SortStrategy<T> strategy;
private List<T> items;
public SortContext(List<T> items) {
this.items = new ArrayList<>(items);
}
public void setStrategy(SortStrategy<T> strategy) {
this.strategy = strategy;
}
public List<T> executeSort() {
if (strategy == null) {
throw new IllegalStateException("请先设置排序策略");
}
return strategy.sort(items);
}
public SortPerformance analyze() {
if (strategy == null) {
throw new IllegalStateException("请先设置排序策略");
}
return strategy.analyzePerformance(items);
}
}
5.3 压缩算法策略
java
java
下载
复制
public interface CompressionStrategy {
byte[] compress(byte[] data) throws IOException;
byte[] decompress(byte[] compressedData) throws IOException;
String getAlgorithmName();
double getCompressionRatio(byte[] original, byte[] compressed);
}
// GZIP压缩策略
public class GzipCompressionStrategy implements CompressionStrategy {
@Override
public byte[] compress(byte[] data) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(bos)) {
gzip.write(data);
}
return bos.toByteArray();
}
@Override
public byte[] decompress(byte[] compressedData) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (GZIPInputStream gzip = new GZIPInputStream(
new ByteArrayInputStream(compressedData))) {
byte[] buffer = new byte[1024];
int len;
while ((len = gzip.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
}
return bos.toByteArray();
}
@Override
public String getAlgorithmName() {
return "GZIP";
}
@Override
public double getCompressionRatio(byte[] original, byte[] compressed) {
return (double) compressed.length / original.length;
}
}
// 压缩管理器
public class CompressionManager {
private CompressionStrategy strategy;
public void setStrategy(CompressionStrategy strategy) {
this.strategy = strategy;
}
public CompressionResult compress(byte[] data) throws IOException {
long startTime = System.currentTimeMillis();
byte[] compressed = strategy.compress(data);
long endTime = System.currentTimeMillis();
double ratio = strategy.getCompressionRatio(data, compressed);
return new CompressionResult(
compressed,
ratio,
endTime - startTime,
data.length,
compressed.length
);
}
}
5.4 验证策略
java
java
下载
复制
public interface ValidationStrategy {
boolean validate(String input);
String getErrorMessage();
ValidationRule getRule();
}
public class EmailValidationStrategy implements ValidationStrategy {
private static final Pattern EMAIL_PATTERN =
Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
@Override
public boolean validate(String input) {
if (input == null) return false;
return EMAIL_PATTERN.matcher(input).matches();
}
@Override
public String getErrorMessage() {
return "邮箱格式不正确";
}
@Override
public ValidationRule getRule() {
return ValidationRule.EMAIL;
}
}
// 验证上下文
public class Validator {
private List<ValidationStrategy> strategies = new ArrayList<>();
public void addStrategy(ValidationStrategy strategy) {
strategies.add(strategy);
}
public ValidationResult validate(String input) {
List<String> errors = new ArrayList<>();
for (ValidationStrategy strategy : strategies) {
if (!strategy.validate(input)) {
errors.add(strategy.getErrorMessage());
}
}
return new ValidationResult(
errors.isEmpty(),
errors,
input
);
}
}
六、优缺点深度解析
6.1 优点分析
6.1.1 开闭原则支持
java
java
下载
复制
// 易于扩展新策略
public class NewPaymentStrategy implements PaymentStrategy {
// 新增支付方式,无需修改现有代码
@Override
public PaymentResult pay(BigDecimal amount) {
// 新支付方式实现
return null;
}
@Override
public String getStrategyName() {
return "NEW_PAYMENT";
}
@Override
public boolean isSupported() {
return true;
}
}
6.1.2 消除条件语句
java
java
下载
复制
// 传统if-else方式(不推荐)
public class BadPaymentProcessor {
public PaymentResult process(String paymentType, BigDecimal amount) {
if ("CREDIT_CARD".equals(paymentType)) {
// 信用卡处理逻辑
} else if ("PAYPAL".equals(paymentType)) {
// PayPal处理逻辑
} else if ("ALIPAY".equals(paymentType)) {
// 支付宝处理逻辑
} else if ("WECHAT_PAY".equals(paymentType)) {
// 微信支付处理逻辑
}
// 每增加一种支付方式就要修改这里
return null;
}
}
// 策略模式方式(推荐)
public class GoodPaymentProcessor {
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public PaymentResult process(BigDecimal amount) {
return strategy.pay(amount);
}
}
6.1.3 算法复用
java
java
下载
复制
// 多个上下文可以共享相同策略
public class StrategyReuseDemo {
public static void main(String[] args) {
PaymentStrategy wechatPay = new WeChatPaymentStrategy("openId123");
// 订单1使用微信支付
PaymentContext order1 = new PaymentContext("ORDER001",
new BigDecimal("100.00"));
order1.setPaymentStrategy(wechatPay);
// 订单2也使用微信支付
PaymentContext order2 = new PaymentContext("ORDER002",
new BigDecimal("200.00"));
order2.setPaymentStrategy(wechatPay); // 复用同一个策略实例
// 可以配置不同的策略参数
PaymentStrategy alipay1 = new AlipayPaymentStrategy("account1");
PaymentStrategy alipay2 = new AlipayPaymentStrategy("account2");
}
}
6.2 缺点分析
6.2.1 策略类数量爆炸
java
java
下载
复制
// 当策略变多时,管理困难
// 策略1
public class CreditCardStrategy implements PaymentStrategy { /* ... */ }
// 策略2
public class PayPalStrategy implements PaymentStrategy { /* ... */ }
// 策略3
public class AlipayStrategy implements PaymentStrategy { /* ... */ }
// 策略4
public class WeChatPayStrategy implements PaymentStrategy { /* ... */ }
// 策略5
public class ApplePayStrategy implements PaymentStrategy { /* ... */ }
// 策略6
public class GooglePayStrategy implements PaymentStrategy { /* ... */ }
// 策略7
public class BankTransferStrategy implements PaymentStrategy { /* ... */ }
// 策略8
public class CryptocurrencyStrategy implements PaymentStrategy { /* ... */ }
// ... 更多策略
解决方案:使用策略工厂和配置文件管理
java
java
下载
复制
@Configuration
public class PaymentStrategyConfig {
@Bean
@ConditionalOnProperty(name = "payment.strategy.credit-card.enabled",
havingValue = "true")
public PaymentStrategy creditCardStrategy() {
return new CreditCardStrategy();
}
@Bean
@ConditionalOnProperty(name = "payment.strategy.paypal.enabled",
havingValue = "true")
public PaymentStrategy paypalStrategy() {
return new PayPalStrategy();
}
// 通过配置文件控制哪些策略启用
}
6.2.2 客户端必须了解所有策略
java
java
下载
复制
// 客户端需要知道所有策略
public class BadClient {
public void processPayment(String type) {
PaymentStrategy strategy;
switch (type) {
case "credit-card":
strategy = new CreditCardStrategy("4111...");
break;
case "paypal":
strategy = new PayPalStrategy("email", "pwd");
break;
case "alipay":
strategy = new AlipayStrategy("account");
break;
// 新增策略需要修改这里
default:
throw new IllegalArgumentException("Unknown type");
}
// ...
}
}
解决方案:使用策略注册表
java
java
下载
复制
public class StrategyRegistry {
private final Map<String, Supplier<PaymentStrategy>> registry = new HashMap<>();
public void register(String type, Supplier<PaymentStrategy> supplier) {
registry.put(type, supplier);
}
public PaymentStrategy getStrategy(String type, Object... params) {
Supplier<PaymentStrategy> supplier = registry.get(type);
if (supplier == null) {
throw new IllegalArgumentException("未注册的策略类型: " + type);
}
return supplier.get();
}
}
6.2.3 性能开销
java
java
下载
复制
public class StrategyPerformanceTest {
@Test
public void testPerformance() {
int iterations = 1000000;
// 直接调用
long directStart = System.nanoTime();
for (int i = 0; i < iterations; i++) {
doDirectPayment();
}
long directTime = System.nanoTime() - directStart;
// 策略模式调用
long strategyStart = System.nanoTime();
for (int i = 0; i < iterations; i++) {
doStrategyPayment();
}
long strategyTime = System.nanoTime() - strategyStart;
System.out.println("直接调用: " + directTime + "ns");
System.out.println("策略调用: " + strategyTime + "ns");
System.out.println("开销比例: " +
(double)(strategyTime - directTime) / directTime * 100 + "%");
}
}
七、使用要点与最佳实践
7.1 策略选择指南
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 算法经常变化 | 策略模式 | 易于扩展和修改算法 |
| 需要消除条件语句 | 策略模式 | 用多态替代条件判断 |
| 多种算法变体 | 策略模式 | 封装算法家族 |
| 算法需要重用 | 策略模式 | 策略可在不同上下文重用 |
| 简单条件判断 | 简单if-else | 避免过度设计 |
| 算法很少变化 | 模板方法模式 | 使用继承更简单 |
7.2 策略模式与相关模式对比
7.2.1 策略模式 vs 工厂模式
java
java
下载
复制
// 工厂模式:创建对象
public class PaymentFactory {
public static Payment createPayment(String type) {
switch (type) {
case "CREDIT_CARD": return new CreditCardPayment();
case "PAYPAL": return new PayPalPayment();
default: throw new IllegalArgumentException();
}
}
}
// 策略模式:选择算法
public class PaymentContext {
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy; // 设置算法
}
public void execute() {
strategy.pay(); // 执行算法
}
}
7.2.2 策略模式 vs 状态模式
java
java
下载
复制
// 状态模式:状态改变时自动切换行为
public class OrderState {
private State currentState;
public void setState(State state) {
this.currentState = state;
}
public void process() {
currentState.handle(); // 行为由状态决定
// 状态可能自动转换
}
}
// 策略模式:手动选择算法
public class Sorter {
private SortStrategy strategy;
public void setStrategy(SortStrategy strategy) {
this.strategy = strategy; // 手动设置策略
}
public void sort() {
strategy.sort(); // 执行选择的算法
}
}
7.3 性能优化技巧
7.3.1 策略对象缓存
java
java
下载
复制
public class StrategyCache {
private final Map<String, PaymentStrategy> cache = new ConcurrentHashMap<>();
private final Map<String, Long> creationTime = new ConcurrentHashMap<>();
private static final long CACHE_TIMEOUT = 30 * 60 * 1000; // 30分钟
public PaymentStrategy getOrCreate(String type, Map<String, Object> params) {
String cacheKey = buildCacheKey(type, params);
// 检查缓存
PaymentStrategy cached = cache.get(cacheKey);
if (cached != null && !isExpired(cacheKey)) {
return cached;
}
// 创建新策略
PaymentStrategy strategy = createStrategy(type, params);
cache.put(cacheKey, strategy);
creationTime.put(cacheKey, System.currentTimeMillis());
return strategy;
}
private boolean isExpired(String cacheKey) {
Long time = creationTime.get(cacheKey);
if (time == null) return true;
return System.currentTimeMillis() - time > CACHE_TIMEOUT;
}
// 清理过期缓存
public void cleanup() {
long now = System.currentTimeMillis();
cache.entrySet().removeIf(entry ->
now - creationTime.getOrDefault(entry.getKey(), 0L) > CACHE_TIMEOUT
);
}
}
7.3.2 延迟初始化策略
java
java
下载
复制
public class LazyStrategy<T extends PaymentStrategy> {
private final Supplier<T> strategySupplier;
private volatile T strategy;
public LazyStrategy(Supplier<T> supplier) {
this.strategySupplier = supplier;
}
public T get() {
if (strategy == null) {
synchronized (this) {
if (strategy == null) {
strategy = strategySupplier.get();
}
}
}
return strategy;
}
}
// 使用示例
public class PaymentService {
private final LazyStrategy<CreditCardStrategy> creditCardStrategy =
new LazyStrategy<>(() -> new CreditCardStrategy("card-number"));
public void process() {
PaymentStrategy strategy = creditCardStrategy.get(); // 延迟初始化
// ...
}
}
7.4 测试策略
java
java
下载
复制
public class StrategyPatternTest {
@Test
public void testCreditCardStrategy() {
// 准备
PaymentStrategy strategy = new CreditCardPaymentStrategy(
"4111111111111111", "TEST USER", "12/30", "123");
PaymentContext context = new PaymentContext("TEST_ORDER",
new BigDecimal("100.00"));
context.setPaymentStrategy(strategy);
// 执行
PaymentResult result = context.executePayment();
// 验证
assertNotNull(result);
assertEquals(PaymentContext.PaymentContextState.SUCCESS,
context.getState());
}
@Test
public void testStrategySwitching() {
// 测试策略切换
PaymentContext context = new PaymentContext("SWITCH_ORDER",
new BigDecimal("200.00"));
// 使用信用卡
PaymentStrategy creditCard = new CreditCardPaymentStrategy(
"4111111111111111", "USER", "12/30", "123");
context.setPaymentStrategy(creditCard);
PaymentResult result1 = context.executePayment();
// 切换到PayPal
PaymentStrategy paypal = new PayPalPaymentStrategy(
"test@example.com", "password");
context.setPaymentStrategy(paypal);
PaymentResult result2 = context.executePayment();
// 验证两次支付使用不同策略
assertNotEquals(result1.getTransactionId(), result2.getTransactionId());
}
@Test
public void testStrategyFactory() {
// 测试工厂创建策略
Map<String, Object> params = new HashMap<>();
params.put("walletAddress", "0x123...");
PaymentStrategy strategy = PaymentStrategyFactory.getStrategy(
"CRYPTO_ETH", params);
assertNotNull(strategy);
assertTrue(strategy instanceof CryptocurrencyPaymentStrategy);
}
}
八、在Spring框架中的实践
8.1 Spring中的策略模式
java
java
下载
复制
// 1. 定义策略接口
public interface NotificationStrategy {
void sendNotification(String message, String recipient);
boolean supports(NotificationType type);
}
// 2. 具体策略实现
@Component
@Order(1)
public class EmailNotificationStrategy implements NotificationStrategy {
@Autowired
private JavaMailSender mailSender;
@Value("${notification.email.from}")
private String fromEmail;
@Override
public void sendNotification(String message, String recipient) {
SimpleMailMessage email = new SimpleMailMessage();
email.setFrom(fromEmail);
email.setTo(recipient);
email.setSubject("系统通知");
email.setText(message);
mailSender.send(email);
}
@Override
public boolean supports(NotificationType type) {
return NotificationType.EMAIL == type;
}
}
@Component
@Order(2)
public class SmsNotificationStrategy implements NotificationStrategy {
@Autowired
private SmsService smsService;
@Override
public void sendNotification(String message, String recipient) {
smsService.sendSms(recipient, message);
}
@Override
public boolean supports(NotificationType type) {
return NotificationType.SMS == type;
}
}
// 3. 策略工厂(使用Spring依赖注入)
@Component
public class NotificationStrategyFactory {
private final List<NotificationStrategy> strategies;
@Autowired
public NotificationStrategyFactory(List<NotificationStrategy> strategies) {
this.strategies = strategies;
}
public NotificationStrategy getStrategy(NotificationType type) {
return strategies.stream()
.filter(strategy -> strategy.supports(type))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(
"不支持的通知类型: " + type));
}
}
// 4. 使用策略的服务
@Service
public class NotificationService {
@Autowired
private NotificationStrategyFactory strategyFactory;
public void sendNotification(NotificationRequest request) {
NotificationStrategy strategy = strategyFactory.getStrategy(
request.getType());
strategy.sendNotification(
request.getMessage(),
request.getRecipient()
);
// 记录日志
logNotification(request, strategy.getClass().getSimpleName());
}
private void logNotification(NotificationRequest request, String strategyName) {
// 记录发送日志
}
}
// 5. 配置类
@Configuration
public class NotificationConfig {
@Bean
@ConditionalOnProperty(name = "notification.email.enabled",
havingValue = "true")
public NotificationStrategy emailNotificationStrategy() {
return new EmailNotificationStrategy();
}
@Bean
@ConditionalOnProperty(name = "notification.sms.enabled",
havingValue = "true")
public NotificationStrategy smsNotificationStrategy() {
return new SmsNotificationStrategy();
}
}
8.2 Spring Boot自动配置策略
java
java
下载
复制
// 自动配置策略
@Configuration
@EnableConfigurationProperties(PaymentProperties.class)
public class PaymentAutoConfiguration {
@Bean
@ConditionalOnClass(name = "com.alipay.api.AlipayClient")
@ConditionalOnProperty(prefix = "payment.alipay", name = "enabled")
public PaymentStrategy alipayStrategy(PaymentProperties properties) {
return new AlipayPaymentStrategy(
properties.getAlipay().getAppId(),
properties.getAlipay().getPrivateKey(),
properties.getAlipay().getPublicKey()
);
}
@Bean
@ConditionalOnBean(PaymentStrategy.class)
public PaymentStrategyRegistry paymentStrategyRegistry(
List<PaymentStrategy> strategies) {
return new PaymentStrategyRegistry(strategies);
}
}
// 配置属性
@ConfigurationProperties(prefix = "payment")
@Data
public class PaymentProperties {
private Alipay alipay = new Alipay();
private WechatPay wechatPay = new WechatPay();
@Data
public static class Alipay {
private boolean enabled = false;
private String appId;
private String privateKey;
private String publicKey;
}
@Data
public static class WechatPay {
private boolean enabled = false;
private String appId;
private String mchId;
private String apiKey;
}
}
九、实际项目中的最佳实践
9.1 微服务架构中的策略模式
java
java
下载
复制
// 服务发现策略
public interface ServiceDiscoveryStrategy {
List<ServiceInstance> discover(String serviceName);
void register(ServiceInstance instance);
void deregister(ServiceInstance instance);
}
// 具体实现
@Component
@Profile("consul")
public class ConsulDiscoveryStrategy implements ServiceDiscoveryStrategy {
@Autowired
private ConsulClient consulClient;
@Override
public List<ServiceInstance> discover(String serviceName) {
// 从Consul发现服务
return consulClient.getHealthServices(serviceName, true, null)
.getValue()
.stream()
.map(this::toServiceInstance)
.collect(Collectors.toList());
}
private ServiceInstance toServiceInstance(HealthService healthService) {
// 转换逻辑
return new ServiceInstance(
healthService.getService().getId(),
healthService.getService().getService(),
healthService.getService().getAddress(),
healthService.getService().getPort()
);
}
}
@Component
@Profile("nacos")
public class NacosDiscoveryStrategy implements ServiceDiscoveryStrategy {
@Autowired
private NamingService namingService;
@Override
public List<ServiceInstance> discover(String serviceName) {
// 从Nacos发现服务
return namingService.getAllInstances(serviceName)
.stream()
.map(this::toServiceInstance)
.collect(Collectors.toList());
}
}
// 服务调用策略
public interface LoadBalanceStrategy {
ServiceInstance select(List<ServiceInstance> instances);
String getStrategyName();
}
@Component
@Qualifier("randomLoadBalance")
public class RandomLoadBalanceStrategy implements LoadBalanceStrategy {
private final Random random = new Random();
@Override
public ServiceInstance select(List<ServiceInstance> instances) {
if (instances.isEmpty()) {
throw new IllegalStateException("没有可用服务实例");
}
return instances.get(random.nextInt(instances.size()));
}
@Override
public String getStrategyName() {
return "RANDOM";
}
}
@Component
@Qualifier("roundRobinLoadBalance")
public class RoundRobinLoadBalanceStrategy implements LoadBalanceStrategy {
private final AtomicInteger counter = new AtomicInteger(0);
@Override
public ServiceInstance select(List<ServiceInstance> instances) {
if (instances.isEmpty()) {
throw new IllegalStateException("没有可用服务实例");
}
int index = Math.abs(counter.getAndIncrement() % instances.size());
return instances.get(index);
}
@Override
public String getStrategyName() {
return "ROUND_ROBIN";
}
}
9.2 配置中心管理策略
yaml
yaml
复制
# application.yml
strategy:
payment:
enabled-strategies:
- credit-card
- alipay
- wechat-pay
default-strategy: alipay
credit-card:
enabled: true
priority: 1
config:
support-3d-secure: true
alipay:
enabled: true
priority: 2
config:
sandbox: false
wechat-pay:
enabled: true
priority: 3
config:
app-id: wx1234567890
9.3 监控和指标收集
java
java
下载
复制
// 策略执行监控
@Aspect
@Component
@Slf4j
public class StrategyExecutionMonitor {
@Autowired
private MeterRegistry meterRegistry;
@Around("@within(org.springframework.stereotype.Component) && " +
"execution(* com.example..*Strategy+.*(..))")
public Object monitorStrategyExecution(ProceedingJoinPoint joinPoint) throws Throwable {
String strategyName = joinPoint.getTarget().getClass().getSimpleName();
String methodName = joinPoint.getSignature().getName();
Timer.Sample sample = Timer.start(meterRegistry);
Counter successCounter = meterRegistry.counter(
"strategy.execution",
"strategy", strategyName,
"method", methodName,
"status", "success"
);
Counter failureCounter = meterRegistry.counter(
"strategy.execution",
"strategy", strategyName,
"method", methodName,
"status", "failure"
);
try {
Object result = joinPoint.proceed();
sample.stop(Timer.builder("strategy.execution.time")
.description("策略执行时间")
.tags("strategy", strategyName, "method", methodName)
.register(meterRegistry));
successCounter.increment();
return result;
} catch (Exception e) {
failureCounter.increment();
throw e;
}
}
}
十、总结与选择建议
10.1 策略模式使用时机
| 场景 | 推荐使用 | 说明 |
|---|---|---|
| 多种算法变体 | ✅ 推荐 | 需要封装不同的算法实现 |
| 消除条件语句 | ✅ 推荐 | 用多态替代复杂if-else |
| 算法需要独立测试 | ✅ 推荐 | 策略可以单独单元测试 |
| 算法需要动态切换 | ✅ 推荐 | 运行时切换策略 |
| 简单算法选择 | ⚠️ 谨慎 | 过度设计风险 |
| 算法极少变化 | ❌ 不推荐 | 增加不必要的复杂度 |
10.2 性能与复杂度平衡
java
java
下载
复制
// 性能敏感场景的优化
public class OptimizedStrategyContext {
// 使用枚举代替字符串匹配
public enum StrategyType {
FAST(new FastStrategy()),
MEMORY_EFFICIENT(new MemoryEfficientStrategy()),
BALANCED(new BalancedStrategy());
private final Strategy strategy;
StrategyType(Strategy strategy) {
this.strategy = strategy;
}
public Strategy getStrategy() {
return strategy;
}
}
// 使用数组替代Map,提高性能
private static final Strategy[] STRATEGY_CACHE = new Strategy[StrategyType.values().length];
static {
for (StrategyType type : StrategyType.values()) {
STRATEGY_CACHE[type.ordinal()] = type.getStrategy();
}
}
public Strategy getStrategy(StrategyType type) {
return STRATEGY_CACHE[type.ordinal()];
}
}
10.3 企业级最佳实践总结
- 策略注册机制:使用工厂模式管理策略创建
- 配置驱动:通过配置文件启用/禁用策略
- 监控告警:为策略执行添加监控指标
- 熔断降级:为策略调用添加熔断机制
- 版本管理:支持策略的版本和灰度发布
- 文档完善:为每个策略提供详细文档
- 测试覆盖:确保每个策略都有充分的单元测试
- 性能基准:建立策略性能基准测试
10.4 代码质量检查规则
java
java
下载
复制
// 自定义Checkstyle规则示例
public class StrategyPatternRules {
// 规则1: 策略接口必须有明确的命名
// 推荐: *Strategy,如PaymentStrategy、SortStrategy
// 不推荐: *Service、*Handler(除非明确是策略)
// 规则2: 策略类应该是无状态的
// 如果需要有状态,考虑使用上下文传递状态
// 规则3: 避免策略类之间的耦合
// 策略之间应该独立,不互相依赖
// 规则4: 策略接口应该保持精简
// 接口方法不宜过多,遵循接口隔离原则
// 规则5: 为策略添加合适的日志
// 记录策略选择和执行情况
}
策略模式是实际项目中最常用的设计模式之一,正确使用可以显著提高代码的可维护性和扩展性。关键在于识别出系统中变化的算法部分,并将其封装为策略,同时确保策略接口的设计足够通用,能够适应未来的变化需求。