设计模式-策略模式

文章目录

  • 一、概述
    • [1.1 结构与角色](#1.1 结构与角色)
    • [1.2 适用场景](#1.2 适用场景)
  • 二、实现方式
    • [2.1 基础实现](#2.1 基础实现)
    • [2.2 运行时动态切换](#2.2 运行时动态切换)
    • [2.3 策略模式 vs 简单 if-else 对比](#2.3 策略模式 vs 简单 if-else 对比)
  • [三、JDK 源码中的策略模式](#三、JDK 源码中的策略模式)
    • [3.1 Comparator------排序策略](#3.1 Comparator——排序策略)
    • [3.2 ThreadPoolExecutor 的拒绝策略](#3.2 ThreadPoolExecutor 的拒绝策略)
    • [3.3 Arrays.sort() 的排序策略选择](#3.3 Arrays.sort() 的排序策略选择)
  • [四、策略模式消除 if-else 实战](#四、策略模式消除 if-else 实战)
    • [4.1 问题场景------促销折扣系统](#4.1 问题场景——促销折扣系统)
    • [4.2 策略模式重构](#4.2 策略模式重构)
    • [4.3 Spring 容器自动注册策略](#4.3 Spring 容器自动注册策略)
    • [4.4 三种消除 if-else 方式对比](#4.4 三种消除 if-else 方式对比)
  • 五、总结

一、概述

在软件开发中,经常会遇到这样的场景:实现某个功能有多种方式(算法),比如支付系统支持微信、支付宝、银行卡等多种支付方式;出行导航支持最短时间、最短距离、最少收费等多种路线策略;促销活动支持满减、折扣、买赠等多种优惠方案。如果将这些不同的实现方式全部写在一个类中,使用大量的 if-elseswitch-case 来区分,会导致代码臃肿、难以维护、扩展困难
if type == A
else if type == B
else if type == C
else if type == D
... 更多分支
客户端代码
策略A实现
策略B实现
策略C实现
策略D实现
策略N实现

每新增一种策略,就要修改客户端代码,违反了开闭原则

策略模式(Strategy Pattern)正是为了解决这个问题而诞生的------它定义一系列算法,将每一个算法封装起来,并使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端。

生活中的策略模式例子:

  • 出行方式:去机场可以坐地铁、打车、坐公交、骑车,每种方式都是一种出行策略,根据时间和费用灵活选择
  • 促销活动:双十一的优惠策略有满减、打折、买赠、秒杀,不同商品可以配置不同的促销策略
  • 排序算法:对不同规模的数据可以选择冒泡排序、快速排序、归并排序等不同策略
  • 压缩工具:支持 ZIP、RAR、7Z 等多种压缩策略,用户按需选择

核心:定义一系列算法,将每一个算法封装起来,并使它们可以互相替换,让算法的变化独立于使用算法的客户端

1.1 结构与角色

策略模式包含以下角色:
持有
实现
实现
实现
委托调用
Client 客户端
Context 上下文
Strategy 策略接口
ConcreteStrategyA 具体策略A
ConcreteStrategyB 具体策略B
ConcreteStrategyC 具体策略C

  • Strategy(策略接口):定义所有支持的算法的公共接口,Context 使用这个接口来调用某个具体策略定义的算法
  • ConcreteStrategy(具体策略):实现策略接口的具体算法
  • Context(上下文):持有策略接口的引用,将客户端的请求委托给策略对象执行,可以在运行时动态切换策略
  • Client(客户端):创建具体策略对象和上下文对象,并将策略对象注入上下文

1.2 适用场景

  • 系统中需要动态地在几种算法中选择一种,避免使用多重条件判断
  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现
  • 不希望客户端知道复杂的、与算法相关的数据结构,想将算法和算法相关的数据封装起来
  • 多个类只在算法或行为上稍有不同的场景

二、实现方式

策略模式的核心实现思路是:将不同的算法分别封装为独立的策略类,它们实现同一个策略接口,上下文类通过组合持有策略接口的引用,将算法的执行委托给策略对象。

2.1 基础实现

以"支付系统"为例,支持微信支付、支付宝支付、银行卡支付三种支付策略:
持有
实现
实现
实现
委托调用
客户端
PaymentContext 支付上下文
PaymentStrategy 策略接口
WechatPay 微信支付
AliPay 支付宝支付
BankPay 银行卡支付

(1)策略接口------支付策略

java 复制代码
/**
 * 策略接口:支付策略
 */
public interface PaymentStrategy {

    /**
     * 支付
     *
     * @param amount 支付金额
     */
    void pay(double amount);
}

(2)具体策略------微信支付、支付宝支付、银行卡支付

java 复制代码
/**
 * 具体策略:微信支付
 */
public class WechatPay implements PaymentStrategy {

    @Override
    public void pay(double amount) {
        System.out.println("微信支付:" + amount + " 元");
    }
}

/**
 * 具体策略:支付宝支付
 */
public class AliPay implements PaymentStrategy {

    @Override
    public void pay(double amount) {
        System.out.println("支付宝支付:" + amount + " 元");
    }
}

/**
 * 具体策略:银行卡支付
 */
public class BankPay implements PaymentStrategy {

    @Override
    public void pay(double amount) {
        System.out.println("银行卡支付:" + amount + " 元");
    }
}

(3)上下文------支付上下文

java 复制代码
/**
 * 上下文:支付上下文
 * 持有 PaymentStrategy 的引用,将支付操作委托给策略对象
 */
public class PaymentContext {

    private PaymentStrategy strategy;

    public PaymentContext(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    /**
     * 设置策略(支持运行时动态切换)
     *
     * @param strategy 支付策略
     */
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    /**
     * 执行支付
     *
     * @param amount 支付金额
     */
    public void executePay(double amount) {
        strategy.pay(amount);
    }
}

(4)客户端调用

java 复制代码
public class StrategyDemo {
    public static void main(String[] args) {
        // 创建上下文,指定微信支付策略
        PaymentContext context = new PaymentContext(new WechatPay());
        context.executePay(100.0);
        // 微信支付:100.0 元

        // 动态切换为支付宝支付
        context.setStrategy(new AliPay());
        context.executePay(200.0);
        // 支付宝支付:200.0 元

        // 动态切换为银行卡支付
        context.setStrategy(new BankPay());
        context.executePay(300.0);
        // 银行卡支付:300.0 元
    }
}

关键点 :上下文 PaymentContext 通过组合持有 PaymentStrategy 接口的引用,将支付操作委托给策略对象。新增支付方式只需要新增一个实现类,无需修改上下文类和已有的策略类,符合开闭原则

2.2 运行时动态切换

策略模式的一大优势是支持运行时动态切换策略。以"出行方式"为例,根据不同场景选择不同的出行策略:

(1)策略接口------出行策略

java 复制代码
/**
 * 策略接口:出行策略
 */
public interface TravelStrategy {

    /**
     * 出行
     *
     * @param distance 距离(公里)
     */
    void travel(double distance);
}

(2)具体策略

java 复制代码
/**
 * 具体策略:地铁出行
 */
public class SubwayStrategy implements TravelStrategy {

    @Override
    public void travel(double distance) {
        System.out.println("乘坐地铁出行 " + distance + " 公里,费用约 " + (3 + distance * 0.5) + " 元");
    }
}

/**
 * 具体策略:打车出行
 */
public class TaxiStrategy implements TravelStrategy {

    @Override
    public void travel(double distance) {
        System.out.println("打车出行 " + distance + " 公里,费用约 " + (13 + distance * 2.3) + " 元");
    }
}

/**
 * 具体策略:骑行出行
 */
public class BikeStrategy implements TravelStrategy {

    @Override
    public void travel(double distance) {
        System.out.println("骑行出行 " + distance + " 公里,费用约 1.5 元");
    }
}

(3)上下文------出行导航

java 复制代码
/**
 * 上下文:出行导航
 * 根据用户选择的策略计算出行方案
 */
public class TravelNavigator {

    private TravelStrategy strategy;

    public TravelNavigator(TravelStrategy strategy) {
        this.strategy = strategy;
    }

    /**
     * 设置出行策略
     *
     * @param strategy 出行策略
     */
    public void setStrategy(TravelStrategy strategy) {
        this.strategy = strategy;
    }

    /**
     * 计算出行方案
     *
     * @param distance 距离(公里)
     */
    public void navigate(double distance) {
        System.out.print("【出行方案】");
        strategy.travel(distance);
    }
}

(4)客户端调用------运行时动态切换

java 复制代码
public class TravelDemo {
    public static void main(String[] args) {
        TravelNavigator navigator = new TravelNavigator(new SubwayStrategy());

        // 3 公里以内------骑行
        double distance = 2.5;
        if (distance <= 3) {
            navigator.setStrategy(new BikeStrategy());
        } else if (distance <= 20) {
            navigator.setStrategy(new SubwayStrategy());
        } else {
            navigator.setStrategy(new TaxiStrategy());
        }
        navigator.navigate(distance);
        // 【出行方案】骑行出行 2.5 公里,费用约 1.5 元

        // 20 公里------打车
        distance = 25;
        if (distance <= 3) {
            navigator.setStrategy(new BikeStrategy());
        } else if (distance <= 20) {
            navigator.setStrategy(new SubwayStrategy());
        } else {
            navigator.setStrategy(new TaxiStrategy());
        }
        navigator.navigate(distance);
        // 【出行方案】打车出行 25.0 公里,费用约 70.5 元
    }
}

注意 :上面的客户端代码中仍然有 if-else 逻辑来选择策略。这部分逻辑可以进一步优化------参见第四章"策略模式消除 if-else 实战"。

2.3 策略模式 vs 简单 if-else 对比

以 3 种支付方式为例:

对比维度 if-else 实现 策略模式
代码结构 所有逻辑集中在一个方法中 每种策略独立封装
新增策略 修改已有代码,加 else-if 新增一个策略类,无需修改已有代码
代码可读性 分支越多越难读 每个策略类职责单一,清晰明了
可维护性 牵一发动全身 策略间互不影响
符合开闭原则
运行时切换 不支持 支持动态切换
类的数量 略多(每种策略一个类)

三、JDK 源码中的策略模式

策略模式在 JDK 中有着广泛的应用,下面来看几个经典的例子。

3.1 Comparator------排序策略

java.util.Comparator 是策略模式最经典的体现。不同的 Comparator 实现就是不同的排序策略,可以灵活地改变排序规则而无需修改被排序的对象。

java 复制代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparatorDemo {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Charlie");
        names.add("Alice");
        names.add("Bob");

        // 策略一:自然排序(字典序)
        Collections.sort(names, Comparator.naturalOrder());
        System.out.println("自然排序:" + names);
        // 自然排序:[Alice, Bob, Charlie]

        // 策略二:按字符串长度排序
        Collections.sort(names, Comparator.comparingInt(String::length));
        System.out.println("长度排序:" + names);
        // 长度排序:[Bob, Alice, Charlie]

        // 策略三:逆序排序
        Collections.sort(names, Comparator.reverseOrder());
        System.out.println("逆序排序:" + names);
        // 逆序排序:[Charlie, Bob, Alice]
    }
}

在这个例子中:

  • Strategy(策略接口)Comparator<T>
  • ConcreteStrategy(具体策略) :各种 Comparator 实现(naturalOrder()comparingInt()reverseOrder() 等)
  • Context(上下文)Collections.sort() / List.sort(),接受 Comparator 作为排序策略

关键点Collections.sort() 方法不需要知道具体的排序策略是什么,它只依赖 Comparator 接口。客户端可以随时传入不同的 Comparator 来改变排序行为,这就是策略模式的精髓。

3.2 ThreadPoolExecutor 的拒绝策略

java.util.concurrent.ThreadPoolExecutor 中的拒绝策略(RejectedExecutionHandler)也是策略模式的典型应用。当线程池的工作队列已满且线程数达到最大值时,新提交的任务需要按照某种策略来处理,JDK 提供了四种内置策略:

java 复制代码
/**
 * 拒绝策略接口 ------ Strategy
 */
public interface RejectedExecutionHandler {

    /**
     * 拒绝任务时的处理方法
     */
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

JDK 内置了四种具体策略:

策略 类名 行为
AbortPolicy ThreadPoolExecutor.AbortPolicy 直接抛出 RejectedExecutionException默认策略
CallerRunsPolicy ThreadPoolExecutor.CallerRunsPolicy 由提交任务的线程自己执行该任务
DiscardPolicy ThreadPoolExecutor.DiscardPolicy 直接丢弃任务,不抛出异常
DiscardOldestPolicy ThreadPoolExecutor.DiscardOldestPolicy 丢弃队列中最旧的任务,然后重新提交当前任务

使用方式:

java 复制代码
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RejectedPolicyDemo {
    public static void main(String[] args) {
        // 创建线程池,指定拒绝策略为 CallerRunsPolicy
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,                              // 核心线程数
                2,                              // 最大线程数
                60L, TimeUnit.SECONDS,          // 空闲线程存活时间
                new LinkedBlockingQueue<>(1),    // 工作队列容量为 1
                new ThreadPoolExecutor.CallerRunsPolicy()  // 拒绝策略
        );

        // 也可以在运行时动态切换拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
    }
}

在这个例子中:

  • Strategy(策略接口)RejectedExecutionHandler
  • ConcreteStrategy(具体策略)AbortPolicyCallerRunsPolicyDiscardPolicyDiscardOldestPolicy
  • Context(上下文)ThreadPoolExecutor,持有拒绝策略的引用

关键点 :线程池通过 setRejectedExecutionHandler() 方法支持运行时动态切换拒绝策略,这正是策略模式的典型特征。

3.3 Arrays.sort() 的排序策略选择

JDK 中 Arrays.sort() 方法根据数组类型和大小自动选择不同的排序算法,这也是策略模式的思想体现:

数组类型 排序策略 说明
基本类型数组 双轴快排(Dual-Pivot Quicksort) 适合基本类型,不要求稳定性
对象数组 TimSort(归并+插入混合排序) 保证稳定性,适合对象比较
小数组 插入排序 元素少于 47 时切换为插入排序
java 复制代码
import java.util.Arrays;
import java.util.Comparator;

public class ArraysSortDemo {
    public static void main(String[] args) {
        // 基本类型------使用双轴快排
        int[] nums = {5, 2, 8, 1, 9};
        Arrays.sort(nums);
        System.out.println("基本类型排序:" + Arrays.toString(nums));
        // 基本类型排序:[1, 2, 5, 8, 9]

        // 对象类型------使用 TimSort
        String[] names = {"Charlie", "Alice", "Bob"};
        Arrays.sort(names);
        System.out.println("对象类型排序:" + Arrays.toString(names));
        // 对象类型排序:[Alice, Bob, Charlie]

        // 自定义排序策略------按长度排序
        Arrays.sort(names, Comparator.comparingInt(String::length));
        System.out.println("自定义策略排序:" + Arrays.toString(names));
        // 自定义策略排序:[Bob, Alice, Charlie]
    }
}

四、策略模式消除 if-else 实战

策略模式最实用的场景之一就是消除代码中大量的 if-elseswitch-case 分支。下面通过一个完整的实战案例,展示如何从 if-else 重构为策略模式。

4.1 问题场景------促销折扣系统

假设有一个电商系统的促销模块,支持多种优惠策略:

java 复制代码
/**
 * 促销服务------if-else 实现
 */
public class PromotionServiceBad {

    /**
     * 计算折扣价格
     *
     * @param type     促销类型
     * @param price    原价
     * @param param    促销参数(如折扣率、满减门槛等)
     * @return 折后价
     */
    public double calculatePrice(String type, double price, double param) {
        if ("DISCOUNT".equals(type)) {
            // 打折策略
            return price * param;
        } else if ("FULL_REDUCTION".equals(type)) {
            // 满减策略
            return price >= param ? price - 20 : price;
        } else if ("BUY_ONE_GET_ONE_FREE".equals(type)) {
            // 买一赠一策略
            return price * 0.5;
        } else if ("CASHBACK".equals(type)) {
            // 返现策略
            return price - param;
        } else {
            throw new IllegalArgumentException("不支持的促销类型:" + type);
        }
    }
}

问题 :每新增一种促销策略,就要修改 calculatePrice 方法,违反开闭原则,且 if-else 分支会越来越多,可读性越来越差。

4.2 策略模式重构

(1)策略接口

java 复制代码
/**
 * 策略接口:促销策略
 */
public interface PromotionStrategy {

    /**
     * 计算折后价格
     *
     * @param price 原价
     * @param param 促销参数
     * @return 折后价
     */
    double calculatePrice(double price, double param);
}

(2)具体策略

java 复制代码
/**
 * 具体策略:打折
 */
public class DiscountStrategy implements PromotionStrategy {

    @Override
    public double calculatePrice(double price, double param) {
        return price * param;
    }
}

/**
 * 具体策略:满减
 */
public class FullReductionStrategy implements PromotionStrategy {

    @Override
    public double calculatePrice(double price, double param) {
        return price >= param ? price - 20 : price;
    }
}

/**
 * 具体策略:买一赠一
 */
public class BuyOneGetOneFreeStrategy implements PromotionStrategy {

    @Override
    public double calculatePrice(double price, double param) {
        return price * 0.5;
    }
}

/**
 * 具体策略:返现
 */
public class CashbackStrategy implements PromotionStrategy {

    @Override
    public double calculatePrice(double price, double param) {
        return price - param;
    }
}

(3)策略工厂------消除 if-else 的关键

java 复制代码
import java.util.HashMap;
import java.util.Map;

/**
 * 策略工厂:通过 Map 注册策略,根据类型获取对应策略
 * 消除 if-else 的关键:用 Map 查找代替条件判断
 */
public class PromotionStrategyFactory {

    private static final Map<String, PromotionStrategy> STRATEGY_MAP = new HashMap<>();

    static {
        // 注册策略
        STRATEGY_MAP.put("DISCOUNT", new DiscountStrategy());
        STRATEGY_MAP.put("FULL_REDUCTION", new FullReductionStrategy());
        STRATEGY_MAP.put("BUY_ONE_GET_ONE_FREE", new BuyOneGetOneFreeStrategy());
        STRATEGY_MAP.put("CASHBACK", new CashbackStrategy());
    }

    /**
     * 获取策略
     *
     * @param type 促销类型
     * @return 对应的促销策略
     */
    public static PromotionStrategy getStrategy(String type) {
        PromotionStrategy strategy = STRATEGY_MAP.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的促销类型:" + type);
        }
        return strategy;
    }

    /**
     * 注册新策略(支持动态扩展)
     *
     * @param type     促销类型
     * @param strategy 促销策略
     */
    public static void registerStrategy(String type, PromotionStrategy strategy) {
        STRATEGY_MAP.put(type, strategy);
    }
}

(4)上下文

java 复制代码
/**
 * 上下文:促销上下文
 */
public class PromotionContext {

    private final PromotionStrategy strategy;

    public PromotionContext(String type) {
        this.strategy = PromotionStrategyFactory.getStrategy(type);
    }

    /**
     * 计算折后价格
     *
     * @param price 原价
     * @param param 促销参数
     * @return 折后价
     */
    public double calculatePrice(double price, double param) {
        return strategy.calculatePrice(price, param);
    }
}

(5)客户端调用

java 复制代码
public class PromotionDemo {
    public static void main(String[] args) {
        // 打折策略------8折
        PromotionContext discount = new PromotionContext("DISCOUNT");
        System.out.println("打折后价格:" + discount.calculatePrice(100, 0.8));
        // 打折后价格:80.0

        // 满减策略------满200减20
        PromotionContext fullReduction = new PromotionContext("FULL_REDUCTION");
        System.out.println("满减后价格:" + fullReduction.calculatePrice(250, 200));
        // 满减后价格:230.0

        // 买一赠一策略
        PromotionContext buyOneGetOne = new PromotionContext("BUY_ONE_GET_ONE_FREE");
        System.out.println("买一赠一价格:" + buyOneGetOne.calculatePrice(100, 0));
        // 买一赠一价格:50.0

        // 返现策略------返现30
        PromotionContext cashback = new PromotionContext("CASHBACK");
        System.out.println("返现后价格:" + cashback.calculatePrice(100, 30));
        // 返现后价格:70.0
    }
}

核心思路 :用 Map<String, Strategy> 代替 if-else,通过策略类型从 Map 中查找对应的策略对象,新增策略只需注册到 Map 中,无需修改任何已有代码。

4.3 Spring 容器自动注册策略

在 Spring 项目中,可以借助依赖注入自动完成策略注册,进一步简化代码:

(1)策略接口添加类型标识

java 复制代码
/**
 * 策略接口:促销策略
 * 增加 getType() 方法用于标识策略类型
 */
public interface PromotionStrategy {

    /**
     * 获取策略类型
     *
     * @return 策略类型标识
     */
    String getType();

    /**
     * 计算折后价格
     *
     * @param price 原价
     * @param param 促销参数
     * @return 折后价
     */
    double calculatePrice(double price, double param);
}

(2)具体策略加上 @Component 注解

java 复制代码
import org.springframework.stereotype.Component;

@Component
public class DiscountStrategy implements PromotionStrategy {

    @Override
    public String getType() {
        return "DISCOUNT";
    }

    @Override
    public double calculatePrice(double price, double param) {
        return price * param;
    }
}

@Component
public class FullReductionStrategy implements PromotionStrategy {

    @Override
    public String getType() {
        return "FULL_REDUCTION";
    }

    @Override
    public double calculatePrice(double price, double param) {
        return price >= param ? price - 20 : price;
    }
}

@Component
public class CashbackStrategy implements PromotionStrategy {

    @Override
    public String getType() {
        return "CASHBACK";
    }

    @Override
    public double calculatePrice(double price, double param) {
        return price - param;
    }
}

(3)Spring 自动注册策略工厂

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 策略工厂:Spring 自动注册
 * 通过 Spring 依赖注入自动收集所有 PromotionStrategy 实现
 * 无需手动注册,新增策略只需添加 @Component 注解即可
 */
@Component
public class SpringPromotionStrategyFactory {

    @Autowired
    private List<PromotionStrategy> strategyList;

    private final Map<String, PromotionStrategy> strategyMap = new HashMap<>();

    @PostConstruct
    public void init() {
        // Spring 自动注入所有 PromotionStrategy 实现
        // 遍历注册到 Map 中
        for (PromotionStrategy strategy : strategyList) {
            strategyMap.put(strategy.getType(), strategy);
        }
    }

    /**
     * 获取策略
     *
     * @param type 促销类型
     * @return 对应的促销策略
     */
    public PromotionStrategy getStrategy(String type) {
        PromotionStrategy strategy = strategyMap.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的促销类型:" + type);
        }
        return strategy;
    }
}

优势 :新增策略时,只需创建一个实现 PromotionStrategy 接口的类并添加 @Component 注解,Spring 会自动发现并注册,完全无需修改任何已有代码,真正实现了开闭原则。

4.4 三种消除 if-else 方式对比

方式 if-else 分支 新增策略 依赖 适用场景
if-else 原始实现 修改已有代码 策略极少且固定
Map 注册策略工厂 新增策略类 + 注册到 Map 普通 Java 项目
Spring 自动注册 新增策略类 + @Component Spring Spring 项目

五、总结

策略模式的核心思想是定义一系列算法,将每一个算法封装起来,并使它们可以互相替换,让算法的变化独立于使用算法的客户端。

优点:

  • 消除 if-else:用策略类代替多重条件判断,代码更清晰
  • 符合开闭原则:新增策略只需新增一个策略类,无需修改已有代码
  • 算法可自由切换:上下文通过组合持有策略引用,支持运行时动态切换
  • 策略可复用:同一策略可在不同上下文中复用
  • 避免多重条件判断:将分支逻辑分散到各个策略类中,每个类职责单一

缺点:

  • 增加类的数量:每种策略都需要一个独立的类,策略越多类越多
  • 客户端必须了解所有策略:客户端需要知道有哪些策略可用,才能选择合适的策略
  • 策略对象可能无法复用:某些策略只在特定场景下使用,可能导致策略类"膨胀"

适用场景:

  • 系统中需要动态地在几种算法中选择一种
  • 需要避免使用多重条件判断(if-else / switch-case)的场景
  • 一个类定义了多种行为,且这些行为以条件语句的形式出现
  • 多个类只在算法或行为上有所不同

策略模式 vs 状态模式 :策略模式和状态模式结构非常相似,都是通过组合持有接口引用来委托行为,但意图不同------策略模式的客户端主动选择 策略,策略之间是平等的替换关系;状态模式的状态由对象内部自动切换,状态之间有流转逻辑。


参考博客:

策略模式 | 菜鸟教程:https://www.runoob.com/design-pattern/strategy-pattern.html

相关推荐
2601_953660371 小时前
Java Map集合详解与实战
java·开发语言·python
星晨羽1 小时前
java通过共享目录协议下载文件到本地
java
YuanDaima20481 小时前
云计算基础与容器技术演进
java·服务器·人工智能·python·深度学习·云计算·个人开发
java1234_小锋1 小时前
SpringBoot可以同时处理多少请求?
java·spring boot·后端
JAVA面经实录9171 小时前
原码反码补码编码架构与进制底层设计思想
java·架构
wangl_921 小时前
初探 C# 15 的 Union Types
java·开发语言·算法·c#·.net·.net core
happymaker06262 小时前
Spring学习日记——DAY06(事务管理)
java·学习·spring
兰令水2 小时前
topcode【随机算法题】【2026.5.14打卡-java版本】
java·算法·leetcode
雪度娃娃2 小时前
结构型设计模式——代理模式
java·c++·设计模式·系统安全·代理模式