策略模式 详解 设计模式

策略模式

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

主要解决: 在有多种算法相似的情况下,使用 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);
    }
}
相关推荐
Scott9999HH5 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔5 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社6 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海6 小时前
python 列表、元组、集合和字典
开发语言·python
克里斯蒂亚诺更新6 小时前
ruoyi角色权限的对应关系
笔记
萧瑟余晖7 小时前
JDK 26 新特性详解
java·开发语言
马优晨8 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a1117769 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
人邮异步社区10 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大10 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf