Skip to main content

策略模式 (Strategy)

场景问题​

问题案例​

考虑一个电商平台的促销活动,针对不同用户、不同时间段采用不同的折扣策略,如满减、打折、返现等。如何灵活切换和扩展这些策略?

不用模式的解决方案​

实现简化版本​

最直接的做法是用if-else或switch语句处理所有策略:

public class Order {
private double price;
private String type; // "discount", "cashback", "fullcut"
public Order(double price, String type) {
this.price = price;
this.type = type;
}
public double getFinalPrice() {
if ("discount".equals(type)) {
return price * 0.8;
} else if ("cashback".equals(type)) {
return price - 20;
} else if ("fullcut".equals(type)) {
return price >= 100 ? price - 30 : price;
}
return price;
}
}

使用示例​

Order order = new Order(120, "discount");
System.out.println(order.getFinalPrice());

有何问题​

  1. 策略扩展不灵活,新增策略需修改原有代码。
  2. 违反开闭原则,代码难以维护。
  3. if-else臃肿,难以阅读。

解决方案​

策略模式的定义​

定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。

应用策略模式的思路​

  • 定义统一的策略接口,各种策略实现该接口。
  • 上下文对象持有策略接口引用,运行时可切换策略。
  • 新增策略无需修改原有代码。

策略模式的结构​

  • Strategy:抽象策略,定义统一接口。
  • DiscountStrategy/CashbackStrategy/FullCutStrategy:具体策略,实现不同算法。
  • Context:上下文,持有策略引用,负责与客户端交互。

策略模式的实现​

// 策略接口
public interface Strategy {
double calculate(double price);
}

// 具体策略
public class DiscountStrategy implements Strategy {
public double calculate(double price) { return price * 0.8; }
}
public class CashbackStrategy implements Strategy {
public double calculate(double price) { return price - 20; }
}
public class FullCutStrategy implements Strategy {
public double calculate(double price) { return price >= 100 ? price - 30 : price; }
}

// 上下文
public class Context {
private Strategy strategy;
public void setStrategy(Strategy strategy) { this.strategy = strategy; }
public double getFinalPrice(double price) {
return strategy.calculate(price);
}
}

使用示例​

public class Client {
public static void main(String[] args) {
Context context = new Context();
context.setStrategy(new DiscountStrategy());
System.out.println(context.getFinalPrice(120));
context.setStrategy(new CashbackStrategy());
System.out.println(context.getFinalPrice(120));
}
}

策略重写示例​

示例结构​


示例代码​

见上文"策略模式的实现"部分。


模式讲解​

策略模式的功能​

  • 动态切换算法,扩展灵活。
  • 满足开闭原则,便于维护。
  • 代码结构清晰,易于阅读。

实现成接口​

  • 策略接口通常定义为接口或抽象类。

使用工厂方法​

  • 可结合工厂方法模式,统一创建策略对象。

切换产品簇​

  • 可用于切换不同的算法族,如不同促销策略。

执行时序图​