好的,策略模式(Strategy Pattern)是一种行为型设计模式,用于定义一系列算法,并将每个算法封装成独立的类,使得它们可以相互替换 。策略模式的核心思想是将算法与使用算法的客户端解耦,让算法的变化独立于客户端的使用。
1.策略模式的核心概念
-
策略接口(Strategy Interface)
定义所有支持的算法的公共接口,所有具体策略类必须实现该接口。
-
具体策略类(Concrete Strategies)
实现策略接口的具体算法。
-
上下文类(Context Class)
持有一个策略接口的引用,并通过该接口调用具体策略的算法。
2.为什么需要策略模式?
-
避免冗长的条件判断 :当代码中存在大量
if-else
或switch-case
来根据条件选择不同算法时,策略模式可以消除这些重复判断。 -
开闭原则(OCP):新增算法时无需修改现有代码,只需添加新的策略类。
-
解耦:将算法逻辑与业务逻辑分离,便于维护和扩展。
3.策略模式的实现步骤
**3.**1. 定义策略接口
java
// 策略接口:定义算法的抽象
public interface PaymentStrategy {
void pay(double amount);
}
3.2. 实现具体策略类
java
// 具体策略:支付宝支付
public class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用支付宝支付:" + amount + "元");
}
}
// 具体策略:微信支付
public class WechatPayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用微信支付:" + amount + "元");
}
}
3.3 定义上下文类(持有策略的选择)
java
// 上下文类:负责调用策略
public class PaymentContext {
private PaymentStrategy strategy;
// 设置策略(通过构造器或Setter注入)
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
// 执行支付
public void executePayment(double amount) {
strategy.pay(amount);
}
// 动态切换策略(可选)
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
}
3.4. 客户端调用
java
public class Client {
public static void main(String[] args) {
// 选择支付宝策略
PaymentContext context = new PaymentContext(new AlipayStrategy());
context.executePayment(100.0); // 输出:使用支付宝支付:100.0元
// 动态切换为微信支付
context.setStrategy(new WechatPayStrategy());
context.executePayment(200.0); // 输出:使用微信支付:200.0元
}
}
4.策略模式的优点
-
灵活切换算法:通过替换策略对象,可以动态改变程序的行为。
-
符合开闭原则:新增算法无需修改已有代码。
-
消除重复代码:避免多层条件分支的臃肿逻辑。
-
高内聚低耦合:每个策略类独立负责自己的算法逻辑。
5.策略模式的典型应用场景
-
支付方式选择:支付宝、微信、信用卡等支付方式的切换。
-
排序算法选择:根据数据规模选择快速排序、归并排序等。
-
折扣策略:满减、打折、积分抵扣等促销活动。
-
游戏中的角色行为:不同武器攻击方式、不同移动策略(行走、飞行)。
6. 策略模式与Spring框架的结合
在Spring中,可以通过依赖注入(DI)动态管理策略实现类。例如:
java
// 1. 定义策略接口
public interface DiscountStrategy {
double applyDiscount(double price);
}
// 2. 实现具体策略类
@Component("vipDiscount") // Spring托管Bean
public class VipDiscountStrategy implements DiscountStrategy {
@Override
public double applyDiscount(double price) {
return price * 0.8; // VIP打8折
}
}
@Component("holidayDiscount")
public class HolidayDiscountStrategy implements DiscountStrategy {
@Override
public double applyDiscount(double price) {
return price * 0.9; // 节假日打9折
}
}
// 3. 上下文类(使用Spring注入策略)
@Service
public class DiscountContext {
private final Map<String, DiscountStrategy> strategyMap;
// 通过构造函数注入所有策略实现类(自动按Bean名称映射)
public DiscountContext(Map<String, DiscountStrategy> strategyMap) {
this.strategyMap = strategyMap;
}
public double executeDiscount(String strategyName, double price) {
DiscountStrategy strategy = strategyMap.get(strategyName);
if (strategy == null) {
throw new IllegalArgumentException("策略不存在");
}
return strategy.applyDiscount(price);
}
}
// 4. 客户端调用
@RestController
public class OrderController {
@Autowired
private DiscountContext discountContext;
@PostMapping("/checkout")
public double checkout(@RequestParam String discountType, @RequestParam double price) {
return discountContext.executeDiscount(discountType, price);
}
}
在上述的示例中,假期折扣和VIP折扣通过@Component注解均交予Spring容器管理,在DiscountContext中通过不同折扣类型的字符串切换,即可实现不同折扣算法的应用。这个实现相较之于前面的基础策略模式,可以看到在Context中,我们将存储Strategy的属性换成了Map,通过键值对配合Spring框架的依赖注入,实现了在调用者类(Controller)中策略的声明以及If-else的彻底清除(不用Map,那意味着需要在Context或者Controller中编写折扣策略的选择代码),降低代码的耦合度,同时也更为灵活地切换折扣算法。
7.策略模式的缺点
-
类数量增多:每个算法对应一个类,可能导致类膨胀。
-
客户端需要了解策略差异:客户端需要知道不同策略的适用场景。
8.总结
策略模式通过将算法封装成独立的类,实现了算法的灵活切换和业务逻辑的解耦。当系统需要在运行时动态选择算法时,策略模式是理想的选择。结合Spring等框架的依赖注入,可以更优雅地管理策略对象,提升代码的可维护性和扩展性。
9.参考
基于SpringBoot的策略模式多实现类注入(Map注入)_springboot 注入map-CSDN博客
......