【设计模式】策略模式(Strategy)详解:把 if-else 变成可切换的算法

文章目录

    • [1. 引言:if-else 正在失控](#1. 引言:if-else 正在失控)
    • [2. 什么是策略模式](#2. 什么是策略模式)
      • [GoF 定义](#GoF 定义)
    • [3. 策略模式的核心思想](#3. 策略模式的核心思想)
    • [4. 策略模式的结构](#4. 策略模式的结构)
    • [5. 示例:商品价格计算](#5. 示例:商品价格计算)
      • [5.1 策略接口](#5.1 策略接口)
      • [5.2 具体策略](#5.2 具体策略)
      • [5.3 上下文](#5.3 上下文)
      • [5.4 客户端使用](#5.4 客户端使用)
    • [6. 策略模式的优点](#6. 策略模式的优点)
    • [7. 策略模式的缺点](#7. 策略模式的缺点)
    • [8. 策略 vs 模板方法](#8. 策略 vs 模板方法)
    • [9. JDK 中的策略模式](#9. JDK 中的策略模式)
    • [10. 适用场景](#10. 适用场景)
    • [11. 一个常见误区](#11. 一个常见误区)
    • 参考

1. 引言:if-else 正在失控

在实际项目中,你很可能见过这样的代码:

java 复制代码
public double calculate(double price, String type) {
    if ("VIP".equals(type)) {
        return price * 0.8;
    } else if ("SVIP".equals(type)) {
        return price * 0.6;
    } else if ("NORMAL".equals(type)) {
        return price;
    }
    return price;
}

问题非常明显:

  • if-else 越来越长
  • 新规则要改老代码
  • 违反开闭原则

当条件分支开始膨胀时,策略模式就是最优解。有选择,就有策略。


2. 什么是策略模式

GoF 定义

定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。

详解:策略模式模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

一句话理解:

把算法当成对象来用。


3. 策略模式的核心思想

策略模式的本质是:

  • 行为抽象
  • 算法解耦
  • 运行期切换

它强调:

用组合代替条件判断。


4. 策略模式的结构

策略模式包含三个角色:

  1. Strategy(策略接口)类

这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

  1. ConcreteStrategy(具体策略)类

实现了抽象策略定义的接口,提供具体的算法实现或行为。

  1. Context(上下文)

持有一个策略类的引用,最终给客户端调用。


5. 示例:商品价格计算

5.1 策略接口

java 复制代码
public interface PriceStrategy {
    double calculate(double price);
}

5.2 具体策略

java 复制代码
public class NormalPriceStrategy implements PriceStrategy {
    public double calculate(double price) {
        return price;
    }
}
java 复制代码
public class VipPriceStrategy implements PriceStrategy {
    public double calculate(double price) {
        return price * 0.8;
    }
}
java 复制代码
public class SvipPriceStrategy implements PriceStrategy {
    public double calculate(double price) {
        return price * 0.6;
    }
}

5.3 上下文

java 复制代码
public class PriceContext {

    private PriceStrategy strategy;

    public PriceContext(PriceStrategy strategy) {
        this.strategy = strategy;
    }

    public double getFinalPrice(double price) {
        return strategy.calculate(price);
    }
}

5.4 客户端使用

java 复制代码
PriceContext context = new PriceContext(new VipPriceStrategy());
System.out.println(context.getFinalPrice(100));

运行时随意切换算法。


6. 策略模式的优点

  1. 消除 if-else
  2. 算法可自由扩展
  3. 符合开闭原则
  4. 运行期灵活切换

7. 策略模式的缺点

  1. 类数量增加
  2. 客户端需理解策略
  3. 策略选择逻辑需额外管理

8. 策略 vs 模板方法

维度 策略模式 模板方法
技术手段 组合 继承
切换方式 运行期 编译期
灵活性 高 中

9. JDK 中的策略模式

Comparator

java 复制代码
Collections.sort(list, comparator);

排序算法不变,比较规则可切换。


10. 适用场景

  • 规则引擎
  • 支付策略
  • 排序算法
  • 风控策略

11. 一个常见误区

策略模式不是为了"多写类",而是为了"少写条件判断"。


参考

策略模式 | 菜鸟教程

《图解设计模式》

策略 - Java教程 - 廖雪峰的官方网站

策略设计模式

相关推荐
曹牧5 分钟前
Spring MVC : Controller 层URL划分
java·运维·服务器·前端
Hespethorn19 分钟前
设计模式是语言缺陷的补丁 —— 从工厂、单例、策略三个模式说起
设计模式
卓怡学长20 分钟前
w203基于springboot钢材仓库管理系统的设计与实现
java·spring boot·spring·intellij-idea
Lost of 程序猿20 分钟前
命令模式实战:把“下单后的动作“打包成可执行的任务
后端·设计模式·c#·asp.net·命令模式
sunburn-22 分钟前
Java 排序算法详细教学:从冒泡排序到快速排序
java·开发语言·数据结构·ide·算法
我是小白呀26 分钟前
编排还是事件协作?用 AcmeFlow 讲清企业 Workflow 的控制权
java·开发语言
一只旭宝30 分钟前
【C++复习】四种类型转换 + 常见设计模式 + Redis/MySQL(后端面试复习完整版)
c++·redis·笔记·mysql·设计模式
深入云栈40 分钟前
Netty 4.2.x 源码深度解析 (十四):KQueue 传输 —— macOS 高性能 IO 的 Netty 实现
java·后端
信誓旦旦的程序猿43 分钟前
【Python 量化取数指南 #13】Python 把行情落库:sqlite 一键存,回测随用随取
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据api
她的男孩1 小时前
头像换了三次还是旧图:秒传 + 预签名 URL + 私有文件权限,四层缓存叠出一个 Bug
java·后端·架构