1. 策略模式概述
策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时选择算法或行为。这种模式的核心思想是将算法封装成独立的类,使得它们可以相互替换,而不会影响使用算法的客户端代码。
1.1 为什么需要策略模式
在实际开发中,我们经常会遇到需要根据不同条件执行不同算法的情况。传统做法是使用大量的if-else或switch-case语句,但这种做法存在几个明显问题:
- 代码臃肿:随着条件分支增多,代码会变得难以维护
- 违反开闭原则:新增或修改算法需要修改原有代码
- 复用性差:算法逻辑与业务代码耦合在一起
策略模式通过将算法抽象为接口,每个具体算法实现该接口,从而解决了上述问题。客户端代码只需要与策略接口交互,而不需要关心具体实现。
1.2 策略模式的核心组件
策略模式包含三个主要角色:
- 策略接口(Strategy):定义所有支持的算法或行为的公共接口
- 具体策略(Concrete Strategy):实现策略接口的具体算法类
- 上下文(Context):持有一个策略对象的引用,负责调用策略
这种结构使得算法可以独立于使用它的客户端而变化,提高了代码的灵活性和可维护性。
2. 策略模式实现详解
2.1 基础实现方式
让我们通过一个完整的支付系统示例来演示策略模式的实现。假设我们需要支持多种支付方式:微信支付、支付宝支付和银行卡支付。
2.1.1 定义策略接口
首先,我们定义支付策略的抽象接口:
java复制/**
* 支付策略接口
*/
public interface PaymentStrategy {
/**
* 执行支付
* @param orderId 订单ID
* @param amount 支付金额
* @return 支付结果
*/
PaymentResult pay(String orderId, double amount);
/**
* 获取支付方式名称
* @return 支付方式名称
*/
String getPaymentMethod();
}
2.1.2 实现具体策略
接下来,我们实现三种具体的支付策略:
java复制/**
* 微信支付策略
*/
public class WeChatPaymentStrategy implements PaymentStrategy {
@Override
public PaymentResult pay(String orderId, double amount) {
// 实际项目中这里会调用微信支付API
System.out.println("使用微信支付完成订单:" + orderId + ",金额:" + amount);
return new PaymentResult(true, "微信支付成功", orderId, amount);
}
@Override
public String getPaymentMethod() {
return "WeChat";
}
}
/**
* 支付宝支付策略
*/
public class AlipayPaymentStrategy implements PaymentStrategy {
@Override
public PaymentResult pay(String orderId, double amount) {
// 实际项目中这里会调用支付宝API
System.out.println("使用支付宝完成订单:" + orderId + ",金额:" + amount);
return new PaymentResult(true, "支付宝支付成功", orderId, amount);
}
@Override
public String getPaymentMethod() {
return "Alipay";
}
}
/**
* 银行卡支付策略
*/
public class BankCardPaymentStrategy implements PaymentStrategy {
@Override
public PaymentResult pay(String orderId, double amount) {
// 实际项目中这里会调用银行接口
System.out.println("使用银行卡完成订单:" + orderId + ",金额:" + amount);
return new PaymentResult(true, "银行卡支付成功", orderId, amount);
}
@Override
public String getPaymentMethod() {
return "BankCard";
}
}
2.1.3 实现上下文类
上下文类负责管理策略对象,并提供给客户端使用:
java复制/**
* 支付上下文
*/
public class PaymentContext {
private PaymentStrategy strategy;
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
/**
* 设置支付策略
* @param strategy 支付策略
*/
public void setPaymentStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
/**
* 执行支付
* @param orderId 订单ID
* @param amount 支付金额
* @return 支付结果
*/
public PaymentResult executePayment(String orderId, double amount) {
return strategy.pay(orderId, amount);
}
}
2.1.4 客户端使用示例
java复制public class Client {
public static void main(String[] args) {
// 创建支付上下文,初始使用微信支付
PaymentContext context = new PaymentContext(new WeChatPaymentStrategy());
String orderId = "ORDER_123456";
double amount = 100.0;
// 使用微信支付
PaymentResult result = context.executePayment(orderId, amount);
System.out.println(result.getMessage());
// 切换到支付宝支付
context.setPaymentStrategy(new AlipayPaymentStrategy());
result = context.executePayment(orderId, amount);
System.out.println(result.getMessage());
// 切换到银行卡支付
context.setPaymentStrategy(new BankCardPaymentStrategy());
result = context.executePayment(orderId, amount);
System.out.println(result.getMessage());
}
}
2.2 策略模式的高级实现
在实际企业级应用中,我们通常会结合Spring框架来实现更灵活的策略模式。
2.2.1 使用Spring管理策略
首先,我们定义一个策略注解来标识不同的支付策略:
java复制/**
* 支付策略注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface PaymentStrategyAnnotation {
/**
* 支付方式类型
*/
String value();
}
然后,我们修改策略实现类,使用注解标识:
java复制@PaymentStrategyAnnotation("WeChat")
public class WeChatPaymentStrategy implements PaymentStrategy {
// 实现代码同上
}
@PaymentStrategyAnnotation("Alipay")
public class AlipayPaymentStrategy implements PaymentStrategy {
// 实现代码同上
}
@PaymentStrategyAnnotation("BankCard")
public class BankCardPaymentStrategy implements PaymentStrategy {
// 实现代码同上
}
2.2.2 策略管理器
创建一个策略管理器,在Spring启动时自动注册所有策略:
java复制@Component
public class PaymentStrategyManager implements ApplicationContextAware {
private final Map<String, PaymentStrategy> strategyMap = new ConcurrentHashMap<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 获取所有PaymentStrategy类型的Bean
Map<String, PaymentStrategy> beans = applicationContext.getBeansOfType(PaymentStrategy.class);
beans.forEach((beanName, strategy) -> {
// 获取策略注解
PaymentStrategyAnnotation annotation = strategy.getClass().getAnnotation(PaymentStrategyAnnotation.class);
if (annotation != null) {
strategyMap.put(annotation.value(), strategy);
System.out.println("注册支付策略: " + annotation.value());
}
});
}
/**
* 根据支付类型获取策略
* @param paymentType 支付类型
* @return 支付策略
*/
public PaymentStrategy getStrategy(String paymentType) {
PaymentStrategy strategy = strategyMap.get(paymentType);
if (strategy == null) {
throw new IllegalArgumentException("不支持的支付方式: " + paymentType);
}
return strategy;
}
}
2.2.3 支付服务
创建支付服务,供业务代码调用:
java复制@Service
public class PaymentService {
@Autowired
private PaymentStrategyManager strategyManager;
/**
* 执行支付
* @param orderId 订单ID
* @param amount 支付金额
* @param paymentType 支付类型
* @return 支付结果
*/
public PaymentResult pay(String orderId, double amount, String paymentType) {
PaymentStrategy strategy = strategyManager.getStrategy(paymentType);
return strategy.pay(orderId, amount);
}
}
2.2.4 控制器示例
java复制@RestController
@RequestMapping("/payment")
public class PaymentController {
@Autowired
private PaymentService paymentService;
@PostMapping("/pay")
public PaymentResult pay(@RequestParam String orderId,
@RequestParam double amount,
@RequestParam String paymentType) {
return paymentService.pay(orderId, amount, paymentType);
}
}
3. 策略模式的最佳实践
3.1 策略选择与创建
在实际项目中,策略对象的创建和管理是一个需要考虑的重要问题。以下是几种常见的策略创建方式:
- 简单工厂模式:创建一个工厂类来实例化策略对象
- 依赖注入:使用Spring等框架管理策略对象
- 原型模式:对于有状态的策略对象,可以使用原型模式创建
3.1.1 策略工厂示例
java复制public class PaymentStrategyFactory {
public static PaymentStrategy getStrategy(String paymentType) {
switch (paymentType) {
case "WeChat":
return new WeChatPaymentStrategy();
case "Alipay":
return new AlipayPaymentStrategy();
case "BankCard":
return new BankCardPaymentStrategy();
default:
throw new IllegalArgumentException("不支持的支付方式: " + paymentType);
}
}
}
3.2 策略模式与模板方法模式结合
在某些场景下,我们可以将策略模式与模板方法模式结合使用。策略接口定义算法骨架,具体策略实现具体步骤。
java复制public abstract class AbstractPaymentStrategy implements PaymentStrategy {
// 模板方法
@Override
public final PaymentResult pay(String orderId, double amount) {
// 1. 参数校验
validateParameters(orderId, amount);
// 2. 执行支付
boolean success = doPay(orderId, amount);
// 3. 记录日志
logPayment(orderId, amount, success);
// 4. 返回结果
return buildResult(orderId, amount, success);
}
protected abstract boolean doPay(String orderId, double amount);
private void validateParameters(String orderId, double amount) {
if (orderId == null || orderId.isEmpty()) {
throw new IllegalArgumentException("订单ID不能为空");
}
if (amount <= 0) {
throw new IllegalArgumentException("支付金额必须大于0");
}
}
private void logPayment(String orderId, double amount, boolean success) {
System.out.printf("支付记录: 订单%s, 金额%.2f, 结果%s%n",
orderId, amount, success ? "成功" : "失败");
}
private PaymentResult buildResult(String orderId, double amount, boolean success) {
String message = success ? "支付成功" : "支付失败";
return new PaymentResult(success, message, orderId, amount);
}
}
具体策略只需要实现doPay方法:
java复制public class WeChatPaymentStrategy extends AbstractPaymentStrategy {
@Override
protected boolean doPay(String orderId, double amount) {
// 调用微信支付API
System.out.println("调用微信支付API...");
return true; // 假设总是成功
}
}
3.3 策略模式与Lambda表达式
在Java 8及以上版本中,我们可以使用Lambda表达式和函数式接口来简化策略模式的实现。
java复制@FunctionalInterface
public interface PaymentStrategy {
PaymentResult pay(String orderId, double amount);
}
public class PaymentContext {
private PaymentStrategy strategy;
public void setPaymentStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public PaymentResult executePayment(String orderId, double amount) {
return strategy.pay(orderId, amount);
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
PaymentContext context = new PaymentContext();
// 使用Lambda表达式定义策略
context.setPaymentStrategy((orderId, amount) -> {
System.out.println("使用自定义支付方式支付订单: " + orderId);
return new PaymentResult(true, "支付成功", orderId, amount);
});
PaymentResult result = context.executePayment("ORDER_123", 100.0);
System.out.println(result.getMessage());
}
}
4. 策略模式在实际项目中的应用
4.1 电商系统中的策略模式应用
在电商系统中,策略模式可以应用于多个场景:
- 支付方式选择:如微信支付、支付宝支付、银行卡支付等
- 优惠券计算:满减、折扣、立减等不同优惠策略
- 运费计算:根据地区、重量、体积等计算运费
- 库存扣减策略:先扣减预售库存还是现货库存
4.1.1 优惠券计算示例
定义优惠券策略接口:
java复制public interface DiscountStrategy {
/**
* 计算优惠后的价格
* @param originalPrice 原价
* @return 优惠后的价格
*/
double applyDiscount(double originalPrice);
}
实现具体优惠策略:
java复制/**
* 满减策略
*/
public class FullReductionDiscount implements DiscountStrategy {
private final double fullAmount;
private final double reductionAmount;
public FullReductionDiscount(double fullAmount, double reductionAmount) {
this.fullAmount = fullAmount;
this.reductionAmount = reductionAmount;
}
@Override
public double applyDiscount(double originalPrice) {
if (originalPrice >= fullAmount) {
return originalPrice - reductionAmount;
}
return originalPrice;
}
}
/**
* 折扣策略
*/
public class PercentageDiscount implements DiscountStrategy {
private final double discountRate; // 0.8表示8折
public PercentageDiscount(double discountRate) {
this.discountRate = discountRate;
}
@Override
public double applyDiscount(double originalPrice) {
return originalPrice * discountRate;
}
}
/**
* 立减策略
*/
public class DirectReductionDiscount implements DiscountStrategy {
private final double reductionAmount;
public DirectReductionDiscount(double reductionAmount) {
this.reductionAmount = reductionAmount;
}
@Override
public double applyDiscount(double originalPrice) {
return Math.max(originalPrice - reductionAmount, 0);
}
}
优惠券上下文:
java复制public class DiscountContext {
private DiscountStrategy strategy;
public DiscountContext(DiscountStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
public double calculatePrice(double originalPrice) {
return strategy.applyDiscount(originalPrice);
}
}
4.2 游戏开发中的策略模式
在游戏开发中,策略模式也有很多应用场景:
- AI行为策略:不同的NPC可以有不同的行为策略
- 伤害计算策略:物理伤害、魔法伤害等不同计算方式
- 移动策略:不同的角色可以有不同的移动方式
4.2.1 AI行为策略示例
定义AI策略接口:
java复制public interface AIStrategy {
void executeBehavior(GameCharacter character);
}
实现具体AI策略:
java复制/**
* 攻击型AI
*/
public class AggressiveAI implements AIStrategy {
@Override
public void executeBehavior(GameCharacter character) {
// 寻找最近的敌人
GameCharacter enemy = findNearestEnemy(character);
// 如果敌人在攻击范围内,则攻击
if (enemy != null && isInAttackRange(character, enemy)) {
character.attack(enemy);
} else {
// 否则向敌人移动
character.moveTo(enemy.getPosition());
}
}
// 辅助方法省略...
}
/**
* 防御型AI
*/
public class DefensiveAI implements AIStrategy {
@Override
public void executeBehavior(GameCharacter character) {
// 检查生命值
if (character.getHealth() < character.getMaxHealth() * 0.3) {
// 生命值低时撤退
character.moveTo(getSafePosition(character));
} else {
// 否则保持防御姿态
character.defend();
}
}
// 辅助方法省略...
}
/**
* 中立型AI
*/
public class NeutralAI implements AIStrategy {
@Override
public void executeBehavior(GameCharacter character) {
// 随机移动或站立不动
if (Math.random() > 0.7) {
character.moveTo(getRandomPosition(character));
}
}
// 辅助方法省略...
}
游戏角色类:
java复制public class GameCharacter {
private AIStrategy aiStrategy;
private Position position;
private double health;
public void setAIStrategy(AIStrategy strategy) {
this.aiStrategy = strategy;
}
public void update() {
aiStrategy.executeBehavior(this);
}
// 其他方法省略...
}
5. 策略模式的优缺点分析
5.1 策略模式的优势
- 开闭原则:可以轻松引入新策略而无需修改现有代码
- 消除条件语句:避免了大量的if-else或switch-case语句
- 提高代码复用:相同策略可以在不同上下文中复用
- 便于单元测试:每个策略可以独立测试
- 运行时灵活性:可以在运行时切换策略
5.2 策略模式的缺点
- 类数量增加:每个策略都需要一个单独的类,可能导致类数量膨胀
- 客户端必须了解策略:客户端需要知道有哪些策略以及它们的区别
- 通信开销:策略和上下文之间可能需要传递大量数据
- 不适合简单场景:对于只有少量固定算法且不常变化的场景,可能增加不必要的复杂性
5.3 何时使用策略模式
策略模式特别适用于以下场景:
- 一个系统需要在多种算法中选择一种
- 需要避免暴露复杂的、与算法相关的数据结构
- 一个类定义了多种行为,并且这些行为以多个条件语句的形式出现
- 算法需要自由切换的场景
- 算法需要独立于使用它的客户端
6. 策略模式与其他模式的关系
6.1 策略模式与状态模式
策略模式和状态模式在结构上非常相似,但它们的意图不同:
- 策略模式:客户端主动选择策略,策略之间通常没有关联
- 状态模式:状态转换由内部条件触发,状态之间通常有关联关系
6.2 策略模式与工厂模式
策略模式常与工厂模式结合使用:
- 策略模式:关注行为的抽象和实现
- 工厂模式:关注对象的创建
通常使用工厂来创建策略对象,然后由上下文使用这些策略。
6.3 策略模式与模板方法模式
策略模式和模板方法模式都用于封装算法:
- 策略模式:通过组合实现,运行时可以替换算法
- 模板方法模式:通过继承实现,编译时确定算法骨架
7. 策略模式在Java和Spring中的应用实例
7.1 Java标准库中的策略模式
-
Comparator接口:用于定义集合排序策略
java复制List<String> names = Arrays.asList("John", "Alice", "Bob"); // 使用不同的排序策略 names.sort(Comparator.naturalOrder()); // 自然排序 names.sort(Comparator.reverseOrder()); // 逆序排序 -
ThreadPoolExecutor的拒绝策略:当任务队列满时的处理策略
java复制ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 ); -
File.listFiles(FilenameFilter):文件过滤策略
java复制File dir = new File("."); // 使用不同的文件过滤策略 File[] javaFiles = dir.listFiles((dir1, name) -> name.endsWith(".java")); File[] txtFiles = dir.listFiles((dir1, name) -> name.endsWith(".txt"));
7.2 Spring框架中的策略模式
-
ResourceLoader:资源加载策略
java复制ResourceLoader loader = new DefaultResourceLoader(); Resource resource = loader.getResource("classpath:application.properties"); -
HandlerMapping:请求映射策略
java复制@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configureHandlerMappings(HandlerMappingRegistry registry) { // 可以注册不同的HandlerMapping策略 registry.order(0).mapping(new RequestMappingHandlerMapping()); } } -
AuthenticationProvider:认证策略
java复制@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 添加不同的认证策略 auth.authenticationProvider(new DaoAuthenticationProvider()); auth.authenticationProvider(new LdapAuthenticationProvider()); } }
8. 策略模式的性能考量
在使用策略模式时,需要考虑以下性能因素:
-
对象创建开销:频繁创建策略对象可能导致性能问题
- 解决方案:使用对象池或重用策略对象
-
方法调用开销:策略接口的方法调用比直接方法调用稍慢
- 解决方案:对于性能关键代码,可以考虑其他优化方式
-
内存占用:大量策略类可能增加内存消耗
- 解决方案:合理设计策略粒度,避免过度细分
-
JIT优化限制:虚拟方法调用可能影响JIT优化
- 解决方案:对于热点代码,可以考虑使用final策略类
9. 策略模式的测试策略
针对策略模式,我们可以采用以下测试方法:
-
单元测试每个策略:确保每个具体策略的正确性
java复制@Test public void testWeChatPaymentStrategy() { PaymentStrategy strategy = new WeChatPaymentStrategy(); PaymentResult result = strategy.pay("TEST_123", 100.0); assertTrue(result.isSuccess()); assertEquals("微信支付成功", result.getMessage()); } -
测试上下文类:验证策略切换和委托是否正确
java复制@Test public void testPaymentContext() { PaymentContext context = new PaymentContext(new WeChatPaymentStrategy()); PaymentResult result = context.executePayment("TEST_123", 100.0); assertTrue(result.isSuccess()); context.setPaymentStrategy(new AlipayPaymentStrategy()); result = context.executePayment("TEST_123", 100.0); assertEquals("支付宝支付成功", result.getMessage()); } -
集成测试:验证整个策略系统的工作流程
java复制@SpringBootTest public class PaymentIntegrationTest { @Autowired private PaymentService paymentService; @Test public void testPaymentWorkflow() { PaymentResult result = paymentService.pay("TEST_123", 100.0, "WeChat"); assertTrue(result.isSuccess()); } } -
性能测试:评估策略模式的性能影响
java复制@Benchmark @BenchmarkMode(Mode.Throughput) public void testStrategyPerformance() { PaymentContext context = new PaymentContext(new WeChatPaymentStrategy()); for (int i = 0; i < 10000; i++) { context.executePayment("TEST_" + i, i % 100); } }
10. 策略模式的扩展与变体
10.1 策略枚举模式
对于策略数量固定且有限的场景,可以使用枚举来实现策略模式:
java复制public enum CalculatorStrategy {
ADD {
@Override
public int calculate(int a, int b) {
return a + b;
}
},
SUBTRACT {
@Override
public int calculate(int a, int b) {
return a - b;
}
},
MULTIPLY {
@Override
public int calculate(int a, int b) {
return a * b;
}
},
DIVIDE {
@Override
public int calculate(int a, int b) {
return a / b;
}
};
public abstract int calculate(int a, int b);
}
// 使用示例
int result = CalculatorStrategy.ADD.calculate(10, 5);
10.2 组合策略模式
有时我们需要组合多个策略来实现更复杂的行为:
java复制public class CompositePaymentStrategy implements PaymentStrategy {
private final List<PaymentStrategy> strategies;
public CompositePaymentStrategy(List<PaymentStrategy> strategies) {
this.strategies = strategies;
}
@Override
public PaymentResult pay(String orderId, double amount) {
PaymentResult finalResult = null;
for (PaymentStrategy strategy : strategies) {
finalResult = strategy.pay(orderId, amount);
if (!finalResult.isSuccess()) {
break;
}
}
return finalResult;
}
}
// 使用示例
List<PaymentStrategy> strategies = Arrays.asList(
new CreditCardPaymentStrategy(),
new PayPalPaymentStrategy(),
new BankTransferPaymentStrategy()
);
PaymentStrategy compositeStrategy = new CompositePaymentStrategy(strategies);
10.3 可配置策略模式
对于需要动态配置的策略,可以将策略配置外部化:
properties复制# payment.properties
payment.strategy.default=WeChat
payment.strategy.alternate=Alipay
java复制public class ConfigurablePaymentStrategy implements PaymentStrategy {
private final PaymentStrategy defaultStrategy;
private final PaymentStrategy alternateStrategy;
public ConfigurablePaymentStrategy(Properties config) {
String defaultType = config.getProperty("payment.strategy.default");
String alternateType = config.getProperty("payment.strategy.alternate");
this.defaultStrategy = PaymentStrategyFactory.getStrategy(defaultType);
this.alternateStrategy = PaymentStrategyFactory.getStrategy(alternateType);
}
@Override
public PaymentResult pay(String orderId, double amount) {
PaymentResult result = defaultStrategy.pay(orderId, amount);
if (!result.isSuccess()) {
result = alternateStrategy.pay(orderId, amount);
}
return result;
}
}
11. 策略模式的反模式与常见错误
11.1 策略模式的反模式
-
策略膨胀:创建过多细粒度的策略类,导致系统复杂
- 解决方案:合理设计策略粒度,合并相关策略
-
上下文过载:上下文类承担了太多与策略无关的职责
- 解决方案:保持上下文简单,只负责策略的委托
-
策略泄露:策略实现依赖上下文内部状态
- 解决方案:通过参数传递所需数据,保持策略独立
11.2 常见错误
-
忽略策略接口:直接使用具体策略类,失去灵活性
java复制// 错误做法:直接依赖具体策略 public class PaymentProcessor { private WeChatPaymentStrategy strategy; // ... } // 正确做法:依赖抽象 public class PaymentProcessor { private PaymentStrategy strategy; // ... } -
策略与状态混淆:错误地将状态模式场景用策略模式实现
- 区分点:策略是外部选择的,状态是内部转换的
-
忽略线程安全:在多线程环境下共享可变策略状态
- 解决方案:确保策略无状态或使用线程安全措施
12. 策略模式在不同语言中的实现
虽然本文主要使用Java示例,但策略模式在其他语言中也有广泛应用:
12.1 Python实现
python复制from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, order_id: str, amount: float) -> dict:
pass
class WeChatPayment(PaymentStrategy):
def pay(self, order_id: str, amount: float) -> dict:
print(f"WeChat支付: 订单{order_id}, 金额{amount}")
return {"status": "success", "message": "WeChat支付成功"}
class PaymentContext:
def __init__(self, strategy: PaymentStrategy):
self._strategy = strategy
def execute_payment(self, order_id: str, amount: float) -> dict:
return self._strategy.pay(order_id, amount)
# 使用示例
context = PaymentContext(WeChatPayment())
result = context.execute_payment("ORDER_123", 100.0)
print(result)
12.2 JavaScript实现
javascript复制// 策略接口
class PaymentStrategy {
pay(orderId, amount) {
throw new Error("必须实现pay方法");
}
}
// 具体策略
class WeChatPayment extends PaymentStrategy {
pay(orderId, amount) {
console.log(`微信支付: 订单${orderId}, 金额${amount}`);
return { success: true, message: "微信支付成功" };
}
}
// 上下文
class PaymentContext {
constructor(strategy) {
this.strategy = strategy;
}
executePayment(orderId, amount) {
return this.strategy.pay(orderId, amount);
}
}
// 使用示例
const context = new PaymentContext(new WeChatPayment());
const result = context.executePayment("ORDER_123", 100);
console.log(result);
12.3 Go实现
go复制package main
import "fmt"
// 策略接口
type PaymentStrategy interface {
Pay(orderId string, amount float64) (bool, string)
}
// 具体策略
type WeChatPay struct{}
func (w WeChatPay) Pay(orderId string, amount float64) (bool, string) {
fmt.Printf("微信支付: 订单%s, 金额%.2f\n", orderId, amount)
return true, "微信支付成功"
}
// 上下文
type PaymentContext struct {
strategy PaymentStrategy
}
func (c *PaymentContext) Execute(orderId string, amount float64) (bool, string) {
return c.strategy.Pay(orderId, amount)
}
func main() {
context := PaymentContext{strategy: WeChatPay{}}
success, msg := context.Execute("ORDER_123", 100.0)
fmt.Printf("结果: %t, 消息: %s\n", success, msg)
}
13. 策略模式在微服务架构中的应用
在微服务架构中,策略模式可以应用于以下场景:
- 服务发现策略:如何发现和选择服务实例
- 负载均衡策略:如何分配请求到不同实例
- 熔断策略:如何处理服务故障
- 重试策略:请求失败时的重试逻辑
- 缓存策略:数据缓存和失效策略
13.1 负载均衡策略示例
定义负载均衡策略接口:
java复制public interface LoadBalanceStrategy {
/**
* 选择服务实例
* @param instances 可用实例列表
* @return 选择的实例
*/
ServiceInstance select(List<ServiceInstance> instances);
}
实现具体策略:
java复制/**
* 随机选择策略
*/
public class RandomLoadBalance implements LoadBalanceStrategy {
@Override
public ServiceInstance select(List<ServiceInstance> instances) {
if (instances.isEmpty()) {
throw new IllegalStateException("没有可用服务实例");
}
int index = ThreadLocalRandom.current().nextInt(instances.size());
return instances.get(index);
}
}
/**
* 轮询选择策略
*/
public class RoundRobinLoadBalance implements LoadBalanceStrategy {
private final AtomicInteger counter = new AtomicInteger(0);
@Override
public ServiceInstance select(List<ServiceInstance> instances) {
if (instances.isEmpty()) {
throw new IllegalStateException("没有可用服务实例");
}
int index = counter.getAndIncrement() % instances.size();
return instances.get(index);
}
}
/**
* 最少活跃数策略
*/
public class LeastActiveLoadBalance implements LoadBalanceStrategy {
@Override
public ServiceInstance select(List<ServiceInstance> instances) {
if (instances.isEmpty()) {
throw new IllegalStateException("没有可用服务实例");
}
return instances.stream()
.min(Comparator.comparingInt(ServiceInstance::getActiveCount))
.orElseThrow();
}
}
负载均衡上下文:
java复制public class LoadBalancer {
private LoadBalanceStrategy strategy;
public LoadBalancer(LoadBalanceStrategy strategy) {
this.strategy = strategy;
}
public ServiceInstance chooseInstance(List<ServiceInstance> instances) {
return strategy.select(instances);
}
public void setStrategy(LoadBalanceStrategy strategy) {
this.strategy = strategy;
}
}
14. 策略模式与领域驱动设计
在领域驱动设计(DDD)中,策略模式可以很好地应用于领域模型的实现:
- 定价策略:不同产品可能有不同的定价策略
- 折扣策略:会员等级对应不同的折扣策略
- 配送策略:不同地区使用不同的配送策略
- 支付策略:不同订单类型使用不同的支付策略
14.1 DDD中的定价策略示例
定义定价策略接口:
java复制public interface PricingStrategy {
/**
* 计算价格
* @param product 产品
* @param quantity 数量
* @return 总价
*/
Money calculatePrice(Product product, int quantity);
}
实现具体策略:
java复制/**
* 标准定价策略
*/
public class StandardPricing implements PricingStrategy {
@Override
public Money calculatePrice(Product product, int quantity) {
return product.getPrice().multiply(quantity);
}
}
/**
* 批量折扣策略
*/
public class BulkDiscountPricing implements PricingStrategy {
private final int threshold;
private final double discountRate;
public BulkDiscountPricing(int threshold, double discountRate) {
this.threshold = threshold;
this.discountRate = discountRate;
}
@Override
public Money calculatePrice(Product product, int quantity) {
Money originalPrice = product.getPrice().multiply(quantity);
if (quantity >= threshold) {
return originalPrice.multiply(discountRate);
}
return originalPrice;
}
}
/**
* 会员定价策略
*/
public class MemberPricing implements PricingStrategy {
private final MemberLevel level;
public MemberPricing(MemberLevel level) {
this.level = level;
}
@Override
public Money calculatePrice(Product product, int quantity) {
Money originalPrice = product.getPrice().multiply(quantity);
return originalPrice.multiply(level.getDiscountRate());
}
}
在领域模型中使用策略:
java复制public class Order {
private List<OrderItem> items;
private PricingStrategy pricingStrategy;
public Order(PricingStrategy pricingStrategy) {
this.pricingStrategy = pricingStrategy;
this.items = new ArrayList<>();
}
public void addItem(Product product, int quantity) {
Money price = pricingStrategy.calculatePrice(product, quantity);
items.add(new OrderItem(product, quantity, price));
}
public Money getTotalPrice() {
return items.stream()
.map(OrderItem::getPrice)
.reduce(Money.ZERO, Money::add);
}
}
15. 策略模式的未来发展趋势
随着编程语言和软件开发实践的发展,策略模式也在不断演进:
-
函数式编程的影响:策略模式与函数式编程的高阶函数概念高度契合
- Java中的Lambda表达式简化了策略实现
- Kotlin/Scala等语言对策略模式有更简洁的表达
-
云原生环境下的策略模式:
- 策略配置的云原生管理(ConfigMap/Secret)
- 策略的热加载和动态更新
-
策略模式与AI:
- 机器学习模型作为策略实现
- 动态策略选择基于预测结果
-
策略模式的DSL化:
- 使用领域特定语言定义策略
- 策略的可视化配置和管理