策略模式 详解 设计模式

策略模式

策略模式是一种行为型设计模式,它定义了一系列算法,将每个算法封装到具有共同接口的独立类中,并且使它们可以相互替换。 策略模式可以让算法的变化独立于使用算法的客户端。

主要解决: 在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

结构

策略模式的主要角色如下:

  • 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。所有具体策略类都实现了该接口。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为
  • 环境/上下文(Context)类:持有一个策略类的引用,负责将客户端的请求委派给具体的策略对象

图例:

在 Java 中使用策略模式的写法:

  1. 定义策略接口 :创建一个接口,用于定义所有具体策略类的公共行为
  2. 创建具体策略类:实现策略接口,并提供具体的算法实现。
  3. 创建上下文类:维护一个对策略接口的引用,并提供方法来设置和切换不同的具体策略类。
  4. 客户端使用:在客户端代码中,创建上下文对象,并设置具体的策略类,然后调用上下文对象的方法来执行具体的算法。
java 复制代码
// 1. 定义策略接口
interface PaymentStrategy { 
    void pay(double amount);
}

// 2. 创建具体策略类
class AliPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via AliPay.");
    }
}

class WeChatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via WeChatPay.");
    }
}

// 3. 创建上下文类
class PaymentContext {
    private PaymentStrategy paymentStrategy;

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

    public void makePayment(double amount) {
        paymentStrategy.pay(amount);
    }
}

// 4. 客户端使用
public class Main {
    public static void main(String[] args) {
        PaymentContext paymentContext = new PaymentContext();

        // 使用支付宝支付
        paymentContext.setPaymentStrategy(new AliPayStrategy());
        paymentContext.makePayment(100.0);

        // 使用微信支付
        paymentContext.setPaymentStrategy(new WeChatPayStrategy());
        paymentContext.makePayment(50.0);
    }
}

代码中创建了策略接口 PaymentStrategy 和两个具体策略类 AliPayStrategyWeChatPayStrategy。然后,创建了上下文类 PaymentContext,它维护了一个对策略接口的引用,并提供了设置和执行具体策略的方法。最后,在客户端 Main 类中,创建了 PaymentContext 的实例,并设置了具体的支付策略,然后进行支付操作。

使用场景:

  • 当有多个相关的类只有行为或算法上稍有不同的情况下,可以考虑使用策略模式。它将算法的变化独立封装到各自的策略类中,易于扩展和维护。

  • 一个系统需要动态地在几种算法中选择一种时,可以将这些行为封装成不同的策略类,并在需要时动态切换。

  • 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。

  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现 ,可将每个条件分支移入它们各自的策略类中以代替这些条件语句

注意事项: 如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

混合模式 是指在策略模式中引入了简单工厂模式或者享元模式等其他设计模式,来减少策略类的数量,简化系统的结构。

举例来说,假设一个系统有多种支付方式,除了支付宝支付和微信支付之外,还有银行卡支付、信用卡支付等多种支付方式。如果每种支付方式都对应一个具体的策略类,随着支付方式的增加,策略类的数量会急剧增加,导致类膨胀问题。为了解决这个问题,可以引入简单工厂模式,将支付方式的创建交给一个工厂类来完成;同时,如果某些支付方式具有相似的功能,可以使用享元模式来共享相同的部分,减少策略对象的数量。

代码案例:

java 复制代码
// 1. 定义策略接口
interface PaymentStrategy { 
    void pay(double amount);
}

// 2. 创建具体策略类
class AliPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via AliPay.");
    }
}

class WeChatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via WeChatPay.");
    }
}

class BankCardPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via BankCard.");
    }
}

class CreditCardPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via CreditCard.");
    }
}

// 3. 创建简单工厂类
class PaymentStrategyFactory {
    private static final Map<String, PaymentStrategy> strategies = new HashMap<>();

    static {
        strategies.put("AliPay", new AliPayStrategy());
        strategies.put("WeChatPay", new WeChatPayStrategy());
        // 可以添加更多支付方式的策略对象
    }

    public static PaymentStrategy getPaymentStrategy(String type) {
        return strategies.get(type);
    }
}

// 4. 客户端使用
public class Main {
    public static void main(String[] args) {
        PaymentStrategy aliPayStrategy = PaymentStrategyFactory.getPaymentStrategy("AliPay");
        aliPayStrategy.pay(100.0);

        PaymentStrategy weChatPayStrategy = PaymentStrategyFactory.getPaymentStrategy("WeChatPay");
        weChatPayStrategy.pay(50.0);

        PaymentStrategy bankCardPayStrategy = PaymentStrategyFactory.getPaymentStrategy("BankCard");
        bankCardPayStrategy.pay(80.0);

        PaymentStrategy creditCardPayStrategy = PaymentStrategyFactory.getPaymentStrategy("CreditCard");
        creditCardPayStrategy.pay(120.0);
    }
}
相关推荐
皮皮林5517 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java
冰_河7 小时前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化
桦说编程10 小时前
从 ForkJoinPool 的 Compensate 看并发框架的线程补偿思想
java·后端·源码阅读
躺平大鹅11 小时前
Java面向对象入门(类与对象,新手秒懂)
java
静水流深_沧海一粟12 小时前
04 | 别再写几十个参数的构造函数了——建造者模式
设计模式
StarkCoder12 小时前
从UIKit到SwiftUI的迁移感悟:数据驱动的革命
设计模式
初次攀爬者12 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺12 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart14 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot