设计模式七:策略模式

概述

策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时动态地选择算法或行为,并将其封装在独立的策略对象中。策略模式通过定义一组相互替换的策略对象,使得算法的选择和使用与客户端代码解耦,提供了灵活性和扩展性。

使用策略模式的场景包括:

  1. 当一个系统需要在运行时根据不同的条件选择不同的算法时,策略模式可以提供一种灵活的算法切换机制。
  2. 当有多个类似的算法,但每个算法有不同的实现细节时,可以使用策略模式将算法的变化独立封装,避免使用条件语句或大量的if-else语句。
  3. 当一个类具有多种行为,每种行为需要在不同情况下进行切换时,可以使用策略模式来管理这些行为。

与策略模式相似的其他模式包括:

  1. 状态模式(State Pattern):状态模式也允许对象在内部状态改变时改变其行为,但与策略模式不同的是,状态模式基于对象的内部状态来决定行为,而策略模式基于外部条件来选择行为。
  2. 命令模式(Command Pattern):命令模式将请求封装为一个对象,并将执行操作的责任委托给不同的对象,而策略模式将算法封装为策略对象,并使得算法的选择和使用与客户端解耦。
  3. 工厂模式(Factory Pattern):工厂模式用于创建对象,而策略模式用于选择算法。工厂模式关注对象的创建和实例化过程,而策略模式关注算法的选择和执行过程。

模型图

示例

假设我们有一个电商平台,需要根据不同的支付方式来计算订单的支付金额。这个场景可以使用策略模式来实现。以下是一个具体的示例:

首先,我们定义一个支付策略接口PaymentStrategy,它包含一个计算支付金额的方法:

public interface PaymentStrategy {
    double calculatePaymentAmount(double orderAmount);
}

然后,我们实现两种不同的支付策略:信用卡支付和支付宝支付。它们分别实现了PaymentStrategy接口:

javaCopy code

public class CreditCardPaymentStrategy implements PaymentStrategy {
    public double calculatePaymentAmount(double orderAmount) {
        // 根据信用卡支付规则计算支付金额
        // 假设这里有一些复杂的计算逻辑
        // 返回计算后的支付金额
    }
}

public class AlipayPaymentStrategy implements PaymentStrategy {
    public double calculatePaymentAmount(double orderAmount) {
        // 根据支付宝支付规则计算支付金额
        // 假设这里有一些复杂的计算逻辑
        // 返回计算后的支付金额
    }
}

接下来,我们创建一个PaymentContext类作为上下文类,它持有一个对PaymentStrategy接口的引用,并提供一个用于设置支付策略的方法和一个用于计算支付金额的方法:

public class PaymentContext {
    private PaymentStrategy paymentStrategy;

    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    public double calculatePaymentAmount(double orderAmount) {
        return paymentStrategy.calculatePaymentAmount(orderAmount);
    }
}

最后,我们可以在客户端代码中使用这些类来计算订单的支付金额:

javaCopy code

public class Client {
    public static void main(String[] args) {
        double orderAmount = 100.0; // 订单金额

        PaymentContext paymentContext = new PaymentContext();

        // 设置信用卡支付策略
        paymentContext.setPaymentStrategy(new CreditCardPaymentStrategy());
        double paymentAmount1 = paymentContext.calculatePaymentAmount(orderAmount);

        // 设置支付宝支付策略
        paymentContext.setPaymentStrategy(new AlipayPaymentStrategy());
        double paymentAmount2 = paymentContext.calculatePaymentAmount(orderAmount);

        System.out.println("Credit Card Payment Amount: " + paymentAmount1);
        System.out.println("Alipay Payment Amount: " + paymentAmount2);
    }
}

在这个示例中,PaymentStrategy接口充当抽象策略,CreditCardPaymentStrategyAlipayPaymentStrategy充当具体策略。PaymentContext作为上下文类,通过设置不同的支付策略来计算订单的支付金额。

优缺点

优点:

  1. 算法的解耦:策略模式将不同的算法封装到独立的策略对象中,使得算法的选择和使用与客户端代码解耦。这样,客户端不需要知道具体的算法实现细节,只需要关注选择合适的策略对象即可。
  2. 可扩展性:由于策略模式将算法封装到独立的策略对象中,因此可以方便地添加新的策略对象,扩展系统的功能。无需修改现有的代码,只需新增一个具体的策略类即可。
  3. 可维护性:策略模式将每个算法实现都封装在单独的策略类中,使得代码更加模块化和可维护。修改或调整某个算法时,只需要修改对应的策略类,不会影响其他部分的代码。
  4. 多态性:策略模式利用面向对象的多态特性,使得不同的策略对象可以替换彼此,实现了动态选择和切换算法的能力。

缺点:

  1. 增加了类的数量:使用策略模式会引入多个策略类,如果策略较多,会增加类的数量,使得代码结构复杂化。
  2. 客户端必须了解不同的策略:虽然策略模式将算法封装起来,但客户端仍然需要了解不同的策略,并选择合适的策略对象。这可能会增加客户端的复杂性。
  3. 策略的选择上移:策略模式将算法的选择上移到客户端,客户端需要明确地选择合适的策略对象。这可能会增加客户端的责任和复杂性。
CONTENTS