前言
策略模式可以来定义一系列的算法,并将每个算法封装起来,使它们可以相互替换。这样,算法的变化就不会影响使用算法的客户。在策略模式中,通常会定义一个抽象的策略类,该类定义了所有策略算法的公共接口。然后,可以为每种具体的策略实现创建一个具体的策略类,该类实现了抽象策略类中定义的接口。最后,可以定义一个上下文类来封装具体的策略对象,并在上下文中提供一个设置或更改策略的方法。
角色
- 抽象策略(Strategy):它是一个抽象角色,通常用于定义所有策略类的公共接口,并且它可以是一个抽象类或接口。
- 具体策略(Concrete Strategy):它是具体的策略类,它实现了抽象策略中的接口,提供了具体的算法实现。
- 上下文(Context):它是一个角色,用于封装策略对象,并且通常提供一个设置或更改策略的接口。
示例
假设要设计一个电商网站的价格策略,可以为不同的客户群定义不同的价格。可以使用策略模式来实现这个功能。
抽象策略类
public abstract class PriceStrategy {
abstract double calculatePrice(double price);
}
具体策略(普通客户价格)
public class RegularPriceStrategy extends PriceStrategy {
@Override
double calculatePrice(double price) {
return price;
}
}
具体策略(VIP客户价格)
public class VIPPriceStrategy extends PriceStrategy {
@Override
double calculatePrice(double price) {
return 0.9 * price;
}
}
具体策略(公司客户价格)
public class CorporatePriceStrategy extends PriceStrategy {
@Override
double calculatePrice(double price) {
return 0.8*price;
}
}
上下文
public class PriceCalculator {
PriceStrategy priceStrategy;
PriceCalculator(PriceStrategy priceStrategy) {
this.priceStrategy = priceStrategy;
}
void setPriceStrategy(PriceStrategy priceStrategy) {
this.priceStrategy = priceStrategy;
}
double calculatePrice(double price) {
return priceStrategy.calculatePrice(price);
}
}
使用
public class Demo {
public static void main(String[] args) {
// 使用策略模式
PriceStrategy regularCustomer = new RegularPriceStrategy();
PriceStrategy vipCustomer = new VIPPriceStrategy();
PriceStrategy corporateCustomer = new CorporatePriceStrategy();
PriceCalculator regularPriceCalculator = new PriceCalculator(regularCustomer);
System.out.println(regularPriceCalculator.calculatePrice(100));
}
}
优缺点
优点
- 策略模式使得算法可以独立于使用它的客户而变化。这样,可以在不改变客户端代码的情况下更换算法,并且可以灵活地增加新的算法。
- 策略模式可以减少if-else或switch语句的使用,从而提高程序的可读性和可维护性。
- 策略模式可以让类库更灵活,因为类库可以提供一些策略类,而客户端可以在运行时决定使用哪种策略。
缺点
- 客户端必须知道所有的策略类,并且必须明确地决定使用哪一个策略类。这就意味着客户端必须理解这些策略类的区别,以便选择合适的策略。
- 策略模式会增加类的数量。在本例中,如果要为每种客户群定义一种价格策略,就需要定义很多具体的策略类。这会增加系统的复杂度。
- 策略模式对“开闭原则”的支持并不太好。在这种模式下,增加新的策略类需要修改抽象