概念
定义一系列算法,把它们一个个封装起来,并且让它们可以互相替换
应用场景
遇到需要根据不同条件选择不同行为的场景时,使用策略模式可以将每一种策略独立封装成单独的类,后续如果要新增、修改策略,只需要扩展新的策略类就行,原有代码不需要改动
选择不同的策略只需要接口使用不同的实现类,避免堆砌大量if else

基本结构

1)策略接口(Strategy):定义所有支持的算法(策略)必须实现的方法
2)具体策略(ConcreteStrategy):实现策略接口,封装具体的算法实现
3)上下文(Context):持有一个策略接口的引用,负责在客户端选择并执行具体的策略
代码实现
以 “电商折扣计算” 为例
策略接口
声明统一的折扣计算方法,抽象了“折扣”行为。所有促销方式只要实现这个接口,就能被系统自由替换调用
public interface DiscountStrategy {
double calculate(double originalPrice);
}
具体策略
具体策略类
public class FullReductionStrategy implements DiscountStrategy {
@Override
public double calculate(double originalPrice) {
if (originalPrice >= 100) {
return originalPrice - 20; // 满减
}
return originalPrice;
}
}
public class PercentageDiscountStrategy implements DiscountStrategy {
@Override
public double calculate(double originalPrice) {
return originalPrice * 0.9; // 打九折
}
}
public class VipDiscountStrategy implements DiscountStrategy {
@Override
public double calculate(double originalPrice) {
return originalPrice * 0.8; // VIP 打八折
}
}
上下文
持有一个折扣策略,包含执行策略的方法
public class PriceCalculator {
private DiscountStrategy strategy;
public void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
public double calculatePrice(double originalPrice) {
if (strategy == null) {
throw new IllegalStateException("未设置折扣策略");
}
return strategy.calculate(originalPrice);
}
}
客户端调用
只需为上下文指定策略并执行即可
public class Client {
public static void main(String[] args) {
PriceCalculator calculator = new PriceCalculator();
double originalPrice = 120.0;
// 使用满减策略
calculator.setStrategy(new FullReductionStrategy());
System.out.println("【满减策略】最终价格:" + calculator.calculatePrice(originalPrice));
// 使用打折策略
calculator.setStrategy(new PercentageDiscountStrategy());
System.out.println("【打折策略】最终价格:" + calculator.calculatePrice(originalPrice));
// 使用 VIP 策略
calculator.setStrategy(new VipDiscountStrategy());
System.out.println("【VIP策略】最终价格:" + calculator.calculatePrice(originalPrice));
}
}
优缺点
优点
1)算法封装:将不同算法封装为策略类,需要切换算法时只需要改变策略对象,不需要修改客户端代码
2)隔离判断条件:将策略的选择(if-else)与策略的执行隔离
缺点
1)增加客户端使用难度:客户端不仅要了解每一种策略还要与“上下文”类进行协作
