定义
策略模式是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互相替换,且算法的变化不会影响到使用算法的客户。通过使用策略模式,算法可以在运行时根据需要动态地进行更换,从而使得程序具有更好的扩展性和维护性。
特点
- 封装算法:将不同的算法封装在独立的类中,客户端无需知道具体的算法实现。
- 互换算法:策略模式使得算法可以在运行时动态替换,而不影响使用这些算法的客户端。
- 开闭原则:通过策略模式,可以在不修改现有代码的情况下添加新的算法。
组成:
- 策略接口(Strategy Interface):定义了一个算法族,所有具体的算法都实现这个接口。
- 具体策略(Concrete Strategy):实现了策略接口的具体算法类。
- 上下文(Context):持有一个策略的引用,并在客户端需要时调用策略的方法。
策略接口
public interface DiscountStrategy {
double calculateDiscount(double price);
}
具体策略
// 无折扣策略
public class NoDiscountStrategy implements DiscountStrategy {
@Override
public double calculateDiscount(double price) {
return price; // 原价,没有折扣
}
}
// 打八折策略
public class PercentageDiscountStrategy implements DiscountStrategy {
private double percentage;
public PercentageDiscountStrategy(double percentage) {
this.percentage = percentage;
}
@Override
public double calculateDiscount(double price) {
return price * (1 - percentage / 100); // 按百分比打折
}
}
// 满减策略
public class ThresholdDiscountStrategy implements DiscountStrategy {
private double threshold;
private double discount;
public ThresholdDiscountStrategy(double threshold, double discount) {
this.threshold = threshold;
this.discount = discount;
}
@Override
public double calculateDiscount(double price) {
return price >= threshold ? price - discount : price;
}
}
创建上下文类
// 上下文类,持有一个策略的引用,并在运行时使用策略
public class ShoppingCart {
private DiscountStrategy discountStrategy;
// 设置折扣策略
public void setDiscountStrategy(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
// 计算最终价格
public double calculateFinalPrice(double price) {
return discountStrategy.calculateDiscount(price);
}
}
使用
public class StrategyPatternExample {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 使用无折扣策略
cart.setDiscountStrategy(new NoDiscountStrategy());
System.out.println("Final Price (No Discount): " + cart.calculateFinalPrice(100));
// 使用百分比折扣策略
cart.setDiscountStrategy(new PercentageDiscountStrategy(20));
System.out.println("Final Price (20% Discount): " + cart.calculateFinalPrice(100));
// 使用满减策略
cart.setDiscountStrategy(new ThresholdDiscountStrategy(100, 15));
System.out.println("Final Price (Threshold Discount): " + cart.calculateFinalPrice(120));
}
}
优点
- 遵循开闭原则:可以在不修改现有代码的情况下引入新的策略。
- 消除条件判断:策略模式通过策略类代替了条件语句(如 if-else 或 switch-case),使代码更具可读性和可维护性。
- 算法独立:不同的算法被封装在独立的类中,彼此独立,可以自由切换和替换。
- 提高代码的灵活性:策略模式使得算法的选择在运行时变得更为灵活,而不是在编译时就被确定。
缺点
- 增加了系统的复杂性:每个具体策略都需要定义一个类,如果策略过多,类的数量会显著增加。
- 策略的选择:客户端必须知道不同策略之间的区别,才能选择合适的策略。
场景
- 需要动态选择算法的场景:当一个系统需要在运行时选择不同的算法时,可以使用策略模式。
- 多重条件语句的替代:当一个系统中存在大量的条件语句来决定不同的行为时,可以考虑使用策略模式来替代这些条件语句。
- 需要避免代码重复的场景:不同的算法通常会有相似的结构,但在某些部分有所不同。使用策略模式可以避免重复代码,提高代码复用性。
总结
策略模式通过将不同的算法封装在独立的策略类中,使得算法之间可以互换,并且能够在运行时动态地选择合适的策略。这种模式在需要动态选择行为、避免条件语句、提高代码可维护性和扩展性方面有着显著的优势。