策略模式

策略模式(Strategy Pattern) 是一种行为型设计模式,它定义了一系列算法,将每种算法封装在独立的策略类中,使它们可以互换。策略模式允许在运行时选择不同的算法或操作,而无需修改使用它们的客户端代码。策略模式适用于有多种行为或算法可以互换的场景,能让代码更加灵活、扩展性更强。

1. 策略模式的结构

策略模式通常包括以下三个核心角色:

  1. 抽象策略(Strategy):定义一组算法的公共接口,通常是一个接口或抽象类,供具体策略实现。
  2. 具体策略(Concrete Strategy):实现抽象策略接口的多个具体类,每个类实现不同的算法或行为。
  3. 上下文(Context):持有一个策略接口的引用,可以动态设置或改变具体策略,负责与客户端代码交互,并在需要时调用策略接口定义的行为。

策略模式的 UML 类图

plaintextCopy code+------------------+         +----------------------+
|     Context      |<------->|      Strategy        |
+------------------+         +----------------------+
|  strategy: Strategy |      |+ algorithmInterface():void|
+------------------+         +----------------------+
|+ setStrategy(Strategy) |  ^
|+ executeStrategy():void |  |
+------------------+         +----------------------+
                           |                     |
                           |                     |
                           V                     V
                 +------------------+    +------------------+
                 | ConcreteStrategyA|    | ConcreteStrategyB|
                 +------------------+    +------------------+
                 |+ algorithmInterface()| |+ algorithmInterface()|
                 +------------------+    +------------------+

2. 策略模式的实现

以下是策略模式的 Java 示例。假设我们要实现一个支付系统,支持不同的支付方式(如支付宝、微信、信用卡等),每种支付方式都有不同的实现逻辑。使用策略模式可以让我们根据需要选择不同的支付策略。

1. 定义策略接口

javaCopy codepublic interface PaymentStrategy {
    void pay(double amount);
}

2. 实现具体策略

支付宝支付策略
javaCopy codepublic class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付 " + amount + " 元");
    }
}
微信支付策略
javaCopy codepublic class WeChatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付 " + amount + " 元");
    }
}
信用卡支付策略
javaCopy codepublic class CreditCardStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("使用信用卡支付 " + amount + " 元");
    }
}

3. 创建上下文类

上下文类持有一个策略接口的引用,负责根据不同的策略执行支付操作:

javaCopy codepublic class PaymentContext {
    private PaymentStrategy paymentStrategy;

    // 设置支付策略
    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    // 执行支付操作
    public void executePayment(double amount) {
        if (paymentStrategy == null) {
            throw new IllegalStateException("支付策略未设置");
        }
        paymentStrategy.pay(amount);
    }
}

4. 客户端代码

在客户端代码中,我们可以根据需要选择不同的支付策略并执行支付:

javaCopy codepublic class Client {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext();

        // 使用支付宝支付
        context.setPaymentStrategy(new AlipayStrategy());
        context.executePayment(100);

        // 使用微信支付
        context.setPaymentStrategy(new WeChatPayStrategy());
        context.executePayment(200);

        // 使用信用卡支付
        context.setPaymentStrategy(new CreditCardStrategy());
        context.executePayment(300);
    }
}

输出结果:

plaintextCopy code使用支付宝支付 100 元
使用微信支付 200 元
使用信用卡支付 300 元

3. 策略模式的优缺点

优点

  1. 扩展性强:添加新策略时,无需修改现有代码,只需新增策略类,符合开闭原则(Open/Closed Principle)。
  2. 避免条件判断:通过将不同的行为封装在独立策略中,消除了在上下文中对条件语句的依赖,代码更加简洁。
  3. 灵活性高:在运行时可以动态切换策略,使代码更加灵活。

缺点

  1. 增加类数量:每个策略都需要创建一个新的类,类的数量可能较多。
  2. 客户端必须了解策略:客户端需要知道有哪些策略类,并且要知道何时使用哪种策略。
  3. 不适合策略过多的场景:如果策略数量过多,可能导致类文件增多,不便于维护。

4. 策略模式的使用场景

策略模式适用于以下场景:

  1. 多种算法或行为可以互换:如支付方式、数据排序方式、不同折扣计算方式等。
  2. 消除大量条件分支:当算法或行为有多个实现且通过条件语句选择时,可以使用策略模式替代条件语句。
  3. 动态行为控制:在运行时需要动态切换行为,比如不同的促销策略等。

5. 策略模式的扩展与优化

1. 使用工厂模式创建策略对象

当策略的选择由特定条件决定时,可以将策略选择逻辑封装在工厂类中,通过工厂模式动态创建策略对象,避免在客户端代码中频繁创建具体策略实例。

javaCopy codepublic class PaymentStrategyFactory {
    public static PaymentStrategy getStrategy(String type) {
        switch (type) {
            case "Alipay":
                return new AlipayStrategy();
            case "WeChat":
                return new WeChatPayStrategy();
            case "CreditCard":
                return new CreditCardStrategy();
            default:
                throw new IllegalArgumentException("未知的支付方式");
        }
    }
}

2. 使用注解和反射动态加载策略

在 Spring 中,可以通过注解、反射或依赖注入(DI)实现策略的自动管理,减少代码中的硬编码。例如,可以将策略类用 @Component 注解标记,然后通过 Spring 容器管理,自动注入到上下文中。

3. 优化策略的选择逻辑

如果策略种类非常多,且经常需要根据复杂条件选择策略,可以使用 策略模式结合状态模式,在不同状态下动态选择合适的策略。

6. 总结

  • 策略模式通过定义一系列可以互换的算法,使客户端代码在运行时动态选择不同的策略。
  • 优势:代码解耦、扩展性强,避免大量条件判断。
  • 劣势:类文件增多,可能会让代码难以管理。
  • 适用场景:多种算法、行为互换,或需要根据条件动态选择算法的场景。

策略模式使得不同算法或行为独立封装,实现了代码的高扩展性和灵活性。

0 0 投票数
Article Rating
订阅评论
提醒
guest
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x