(行为型模式)策略模式

106 阅读3分钟

前言

策略模式可以来定义一系列的算法,并将每个算法封装起来,使它们可以相互替换。这样,算法的变化就不会影响使用算法的客户。在策略模式中,通常会定义一个抽象的策略类,该类定义了所有策略算法的公共接口。然后,可以为每种具体的策略实现创建一个具体的策略类,该类实现了抽象策略类中定义的接口。最后,可以定义一个上下文类来封装具体的策略对象,并在上下文中提供一个设置或更改策略的方法。

角色

  • 抽象策略(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));
    }
}

优缺点

优点

  1. 策略模式使得算法可以独立于使用它的客户而变化。这样,可以在不改变客户端代码的情况下更换算法,并且可以灵活地增加新的算法。
  2. 策略模式可以减少if-else或switch语句的使用,从而提高程序的可读性和可维护性。
  3. 策略模式可以让类库更灵活,因为类库可以提供一些策略类,而客户端可以在运行时决定使用哪种策略。

缺点

  1. 客户端必须知道所有的策略类,并且必须明确地决定使用哪一个策略类。这就意味着客户端必须理解这些策略类的区别,以便选择合适的策略。
  2. 策略模式会增加类的数量。在本例中,如果要为每种客户群定义一种价格策略,就需要定义很多具体的策略类。这会增加系统的复杂度。
  3. 策略模式对“开闭原则”的支持并不太好。在这种模式下,增加新的策略类需要修改抽象