策略模式(Strategy Pattern)深度解析教程

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 策略模式属于行为型设计模式,通过定义算法族并将其封装为独立的策略类,使得算法可以动态切换且与使用它的客户端解耦。该模式通过组合替代继承,符合开闭原则(对扩展开放,对修改关闭)。

一、模式定义

策略模式属于行为型设计模式,通过定义算法族并将其封装为独立的策略类,使得算法可以动态切换且与使用它的客户端解耦。该模式通过组合替代继承,符合开闭原则(对扩展开放,对修改关闭)。

二、核心角色

  1. Strategy(策略接口)

    • 定义所有支持的算法的公共接口
  2. ConcreteStrategy(具体策略)

    • 实现策略接口的具体算法
  3. Context(上下文)

    • 持有策略引用,提供修改策略的方法
    • 将客户端请求委托给当前策略

三、经典实现(电商促销场景)

// 1. 策略接口
public interface DiscountStrategy {
    double applyDiscount(double originalPrice);
}

// 2. 具体策略实现
// 无折扣策略
public class NoDiscountStrategy implements DiscountStrategy {
    @Override
    public double applyDiscount(double originalPrice) {
        return originalPrice;
    }
}

// 满减策略
public class FullReductionStrategy implements DiscountStrategy {
    private final double fullAmount;
    private final double reduction;

    public FullReductionStrategy(double fullAmount, double reduction) {
        this.fullAmount = fullAmount;
        this.reduction = reduction;
    }

    @Override
    public double applyDiscount(double originalPrice) {
        return originalPrice >= fullAmount ? 
            originalPrice - reduction : originalPrice;
    }
}

// 百分比折扣策略
public class PercentageDiscountStrategy implements DiscountStrategy {
    private final double percentage;

    public PercentageDiscountStrategy(double percentage) {
        this.percentage = percentage;
    }

    @Override
    public double applyDiscount(double originalPrice) {
        return originalPrice * (1 - percentage);
    }
}

// 3. 上下文类
public class PricingContext {
    private DiscountStrategy strategy;

    public PricingContext(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    public double calculatePrice(double originalPrice) {
        return strategy.applyDiscount(originalPrice);
    }
}

// 4. 客户端使用
public class ECommerceApp {
    public static void main(String[] args) {
        // 初始策略:无折扣
        PricingContext context = new PricingContext(new NoDiscountStrategy());
        double price = 500.0;

        System.out.println("原价: " + price);
        System.out.println("默认策略价格: " + context.calculatePrice(price));

        // 切换为满减策略(满400减100)
        context.setStrategy(new FullReductionStrategy(400, 100));
        System.out.println("满减策略价格: " + context.calculatePrice(price));

        // 切换为百分比折扣(8折)
        context.setStrategy(new PercentageDiscountStrategy(0.2));
        System.out.println("百分比折扣价格: " + context.calculatePrice(price));
    }
}

/* 输出:
原价: 500.0
默认策略价格: 500.0
满减策略价格: 400.0
百分比折扣价格: 400.0
*/

四、模式结构UML

          _________________________
         |       Strategy         |
         |------------------------|
         | + executeAlgorithm()   |
         |________________________|
                    ▲
       ____________|_____________
      |            |            |
______▼______  ____▼______  _____▼______
| Concrete  | | Concrete  | | Concrete  |
| StrategyA | | StrategyB | | StrategyC |
|___________| |___________| |___________|
                    ▲
                    |
               _____▼_____
              |  Context  |
              |-----------|
              | - strategy|
              |___________|

五、模式优劣分析

优势:

  • 避免使用多重条件判断语句
  • 符合开闭原则,新增策略无需修改现有代码
  • 算法可自由切换和组合
  • 便于单元测试(每个策略可独立测试)

劣势:

  • 客户端必须了解不同策略的区别
  • 策略类数量可能膨胀(需配合工厂模式管理)
  • 增加对象数量(每个策略都是独立对象)

六、应用场景

  1. 支付方式选择(支付宝、微信、银行卡等)
  2. 排序算法切换(快速排序、归并排序、冒泡排序)
  3. 文件解析策略(JSON、XML、CSV解析器)
  4. 导航策略(步行导航、驾车导航、公共交通)
  5. 压缩算法选择(ZIP、RAR、7z压缩策略)

七、Java标准库应用

  • Comparator接口
// 策略模式在排序中的应用
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5);

// 使用不同排序策略
Collections.sort(numbers, Comparator.naturalOrder());  // 升序策略
Collections.sort(numbers, Comparator.reverseOrder()); // 降序策略
  • ThreadPoolExecutor拒绝策略
// 线程池拒绝策略实现
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2, 4, 60, TimeUnit.SECONDS, 
    new LinkedBlockingQueue<>(10),
    new ThreadPoolExecutor.AbortPolicy()  // 拒绝策略
);

八、与相似模式对比

模式 核心区别
工厂模式 关注对象创建,策略模式关注行为选择
命令模式 封装操作请求,策略模式封装算法实现
状态模式 状态转移自动发生,策略需要显式选择

九、高级应用技巧

  • 策略工厂管理
public class DiscountStrategyFactory {
    private static final Map<String, DiscountStrategy> strategies = new HashMap<>();

    static {
        strategies.put("NONE", new NoDiscountStrategy());
        strategies.put("FULL_100", new FullReductionStrategy(400, 100));
        strategies.put("20%OFF", new PercentageDiscountStrategy(0.2));
    }

    public static DiscountStrategy getStrategy(String strategyKey) {
        return strategies.getOrDefault(strategyKey, new NoDiscountStrategy());
    }
}

// 使用示例
DiscountStrategy strategy = DiscountStrategyFactory.getStrategy("20%OFF");
  • 组合策略
// 策略组合器
public class CombinedDiscountStrategy implements DiscountStrategy {
    private final List<DiscountStrategy> strategies;

    public CombinedDiscountStrategy(DiscountStrategy... strategies) {
        this.strategies = Arrays.asList(strategies);
    }

    @Override
    public double applyDiscount(double originalPrice) {
        double currentPrice = originalPrice;
        for (DiscountStrategy strategy : strategies) {
            currentPrice = strategy.applyDiscount(currentPrice);
        }
        return currentPrice;
    }
}

// 使用示例
DiscountStrategy combined = new CombinedDiscountStrategy(
    new FullReductionStrategy(300, 50),
    new PercentageDiscountStrategy(0.1)
);
  • Spring框架集成
// 通过@Qualifier注入不同策略
@Service
public class PaymentService {
    private final PaymentStrategy strategy;

    @Autowired
    public PaymentService(@Qualifier("alipayStrategy") PaymentStrategy strategy) {
        this.strategy = strategy;
    }
}

// 策略接口
public interface PaymentStrategy {
    void processPayment(BigDecimal amount);
}

// 具体策略实现
@Service("alipayStrategy")
public class AlipayStrategy implements PaymentStrategy { /*...*/ }

@Service("wechatPayStrategy")
public class WechatPayStrategy implements PaymentStrategy { /*...*/ }

十、最佳实践建议

  1. 策略单一职责
    每个策略类只负责一个具体的算法实现
  2. 无状态策略
    尽量设计无状态的策略对象,方便复用
  3. 策略文档化
    为每个策略编写清晰的文档说明使用场景
  4. 性能优化
    对高频使用的策略考虑对象池技术
  5. 防御式编程
    在上下文类中进行参数校验:
public void setStrategy(DiscountStrategy strategy) {
    if (strategy == null) {
        throw new IllegalArgumentException("Strategy cannot be null");
    }
    this.strategy = strategy;
}

扩展示例:文件加密策略

// 策略接口
public interface EncryptionStrategy {
    String encrypt(String content);
    String decrypt(String encryptedContent);
}

// AES加密策略
public class AesEncryptionStrategy implements EncryptionStrategy {
    // 实现AES加密算法...
}

// RSA加密策略
public class RsaEncryptionStrategy implements EncryptionStrategy {
    // 实现RSA加密算法...
}

// 加密上下文
public class FileEncryptor {
    private EncryptionStrategy strategy;

    public FileEncryptor(EncryptionStrategy strategy) {
        this.strategy = strategy;
    }

    public void encryptFile(String inputPath, String outputPath) {
        String content = readFile(inputPath);
        String encrypted = strategy.encrypt(content);
        writeFile(outputPath, encrypted);
    }

    // 文件读写方法...
}
相关文章
|
2月前
|
域名解析 弹性计算 负载均衡
新手上云教程参考:阿里云服务器租用、域名注册、备案及域名解析流程图文教程
对于想要在阿里云上搭建网站或应用的用户来说,购买阿里云服务器和注册域名,绑定以及备案的流程至关重要。本文将以图文形式为您介绍阿里云服务器购买、域名注册、备案及绑定的全流程,以供参考,帮助用户轻松上手。
|
2月前
|
存储 弹性计算 人工智能
阿里云发票申请图文教程及常见问题解析
在购买完阿里云服务器或者其他云产品之后,如何申请发票成为了许多用户关注的焦点。尤其是对于初次购买阿里云服务器的用户来说,发票申请流程可能并不熟悉。本文将为大家详细介绍阿里云服务器购买之后如何申请发票,以及申请过程中可能遇到的常见问题,帮助大家轻松完成发票申请。
|
2月前
|
弹性计算 运维 网络安全
阿里云轻量应用服务器产品解析与搭建个人博客网站教程参考
轻量应用服务器(Simple Application Server)作为阿里云面向单机应用场景推出的云服务器产品,以其一键部署、一站式管理、高性价比等特性,深受个人开发者、中小企业及入门级用户的喜爱。本文将全面解析阿里云轻量应用服务器的产品优势、应用场景、使用须知,以及使用轻量应用服务器搭建个人博客网站的详细教程,帮助用户更好地了解和使用这一产品。
|
4月前
|
域名解析 弹性计算 安全
阿里云服务器租用、注册域名、备案及域名解析完整流程参考(图文教程)
对于很多初次建站的用户来说,选购云服务器和注册应及备案和域名解析步骤必须了解的,目前轻量云服务器2核2G68元一年,2核4G4M服务器298元一年,域名注册方面,阿里云推出域名1元购买活动,新用户注册com和cn域名2年首年仅需0元,xyz和top等域名首年仅需1元。对于建站的用户来说,购买完云服务器并注册好域名之后,下一步还需要操作备案和域名绑定。本文为大家展示阿里云服务器的购买流程,域名注册、绑定以及备案的完整流程,全文以图文教程形式为大家展示具体细节及注意事项,以供新手用户参考。
|
5月前
|
JSON API 数据格式
二维码操作[二维码解析基础版]免费API接口教程
此接口用于解析标准二维码内容,支持通过BASE64编码或远程图片路径提交图片。请求需包含用户ID、用户KEY、图片方式及图片地址等参数,支持POST和GET方式。返回结果包括状态码和消息内容,适用于图片元素简单的二维码解析。
|
5月前
|
API 数据安全/隐私保护
抖音视频,图集无水印直链解析免费API接口教程
该接口用于解析抖音视频和图集的无水印直链地址。请求地址为 `https://cn.apihz.cn/api/fun/douyin.php`,支持POST或GET请求。请求参数包括用户ID、用户KEY和视频或图集地址。返回参数包括状态码、信息提示、作者昵称、标题、视频地址、封面、图集和类型。示例请求和返回数据详见文档。
|
6月前
|
域名解析 网络协议
邮箱域名解析后收不到短信?三步修复教程
邮箱域名解析后收不到短信?三步修复教程
|
6月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入解析与应用
【10月更文挑战第8天】 在软件开发的浩瀚宇宙中,设计模式如同星辰指引,照亮了代码设计与架构的航道。本文旨在深入探索PHP语境下策略模式(Strategy Pattern)的精髓,不仅剖析其内核原理,还将其融入实战演练,让理论在实践中生根发芽。策略模式,作为解决“如何优雅地封装算法族”的答案,以其独特的灵活性与扩展性,赋予PHP应用以动态变换行为的能力,而无需牵动既有的类结构。
79 2
|
6月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入解析与实践
【10月更文挑战第9天】 策略模式是一种行为设计模式,它允许在运行时选择算法的行为。在PHP开发中,通过使用策略模式,我们可以轻松切换算法或逻辑处理方式而无需修改现有代码结构。本文将深入探讨策略模式的定义、结构以及如何在PHP中实现该模式,并通过实际案例展示其应用价值和优势。
71 1
|
6月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入解析与实践
在PHP开发中,设计模式是提高代码可读性、可维护性和扩展性的重要工具。本文将深入探讨策略模式这一行为型设计模式,通过分析其定义、结构、使用场景以及在PHP中的实际应用,帮助开发者更好地理解和运用策略模式来优化自己的项目。不同于传统摘要的简洁概述,本文摘要部分将详细阐述策略模式的核心理念和在PHP中的实现方法,为读者提供清晰的指引。

推荐镜像

更多
下一篇
oss创建bucket