当前位置: 首页 > article >正文

【设计模式】策略模式定义及其实现代码示例

文章目录

    • 一、策略模式
      • 1.1 策略模式的定义
      • 1.2 策略模式的参与者
      • 1.3 策略模式的优点
      • 1.4 策略模式的缺点
      • 1.5 策略模式的使用场景
    • 二、策略模式简单实现
      • 2.1 案例描述
      • 2.2 实现代码
    • 三、策略模式的代码优化
      • 3.1 优化思路
      • 3.2 抽象策略接口
      • 3.3 上下文
      • 3.4 具体策略实现类
      • 3.5 测试
    • 参考资料

完整案例代码:java-demos/design-pattern-demos/strategy-pattern at main · idealzouhu/java-demos

一、策略模式

1.1 策略模式的定义

策略模式(Strategy Pattern)定义如下:

Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。)

1.2 策略模式的参与者

策略模式的参与者主要有:

  • Context(上下文类):它持有一个 Strategy 对象,用于调用具体策略的方法。客户端通常只需要与 Context 交互,而不直接接触具体的策略实现
  • Strategy(策略接口):定义了算法的通用接口,所有具体策略都实现这个接口。
  • ConcreteStrategy(具体策略类):实现 Strategy 接口的具体算法类,不同的策略类提供不同的算法实现。

1.3 策略模式的优点

  • 避免使用多重条件判断:策略模式可以取代if-elseswitch-case的条件分支。

1.4 策略模式的缺点

  • 策略数量可能会增多:如果策略太多,会增加类的数量,维护成本上升。如果 if-else 判断分支不多并且是固定的,那就使用策略模式即可。

1.5 策略模式的使用场景

  • 算法/行为自由切换: 比如支付系统中,可以通过策略模式动态选择不同的支付方式(微信支付、支付宝支付、信用卡支付等)。
  • 屏蔽算法底层细节:只用知道算法名字即可

二、策略模式简单实现

2.1 案例描述

假设我们有一个系统,它可以根据不同的需求选择不同的排序算法,比如快速排序、冒泡排序、归并排序等。通过策略模式,我们可以将这些不同的算法作为策略类进行实现。

2.2 实现代码

// 策略接口
interface SortStrategy {
    void sort(int[] array);
}

// 具体策略类:快速排序
class QuickSortStrategy implements SortStrategy {
    @Override
    public void sort(int[] array) {
        // 快速排序算法实现
        System.out.println("Using Quick Sort");
        // 排序逻辑
    }
}

// 具体策略类:冒泡排序
class BubbleSortStrategy implements SortStrategy {
    @Override
    public void sort(int[] array) {
        // 冒泡排序算法实现
        System.out.println("Using Bubble Sort");
        // 排序逻辑
    }
}

// 上下文类:负责使用策略
class SortingContext {
    private SortStrategy strategy;
    
    // 设置策略
    public void setStrategy(SortStrategy strategy) {
        this.strategy = strategy;
    }
    
    // 执行排序
    public void executeSort(int[] array) {
        strategy.sort(array);
    }
}

// 测试
public class StrategyPatternExample {
    public static void main(String[] args) {
        SortingContext context = new SortingContext();
        
        // 使用快速排序策略
        context.setStrategy(new QuickSortStrategy());
        context.executeSort(new int[]{3, 1, 2});
        
        // 使用冒泡排序策略
        context.setStrategy(new BubbleSortStrategy());
        context.executeSort(new int[]{3, 1, 2});
    }
}

三、策略模式的代码优化

3.1 优化思路

优化思路为使用 @Component 修饰具体策略类,从而让 Spring 提供的 IoC 容器自动添加策略类,从而实现开闭原则。

注意事项,如果你的策略实现类被初始化的时间晚于 onApplicationEvent 方法的调用,可能会导致在注册策略时未能找到这些策略。确保所有策略组件在 onApplicationEvent 被调用之前已经被创建和注册。

3.2 抽象策略接口

AbstractExecuteStrategy 定义了一个策略执行的基本框架,供具体策略类实现。主要方法有:

  • mark():默认返回策略标识的字符串,可以被具体策略类重写以返回唯一标识。
  • patternMatchMark():用于模式匹配的标识,允许根据一定模式选择策略。
  • execute(REQUEST requestParam):执行策略的方法,接受一个请求参数,默认实现为空,具体策略类可以重写。
  • executeResp(REQUEST requestParam):执行策略并返回结果的方法,接受请求参数并返回响应,默认实现返回null,具体策略类可以重写。
/**
 * 策略执行抽象接口
 *
 */
public interface AbstractExecuteStrategy<REQUEST, RESPONSE>  {
    /**
     * 执行策略标识
     * 用于标识具体的执行策略
     *
     */
    default String mark() {
        return null;
    }

    /**
     * 执行策略范匹配标识
     * 用于在多个策略中通过模式匹配选择合适的策略执行
     *
     */
    default String patternMatchMark() {
        return null;
    }

    /**
     * 执行策略
     *
     * @param requestParam 执行策略所需的参数,类型为REQUEST
     */
    default void execute(REQUEST requestParam) {

    }

    /**
     * 执行策略,带有返回值
     *
     * @param requestParam 执行策略所需的参数,类型为REQUEST
     * @return 执行策略后返回值,类型为RESPONSE
     */
    default RESPONSE executeResp(REQUEST requestParam) {
        return null;
    }
}

3.3 上下文

AbstractStrategyChoose 类用于管理和选择具体的策略,并执行对应的策略。主要方法有:

  • choose(String mark, Boolean predicateFlag):如果predicateFlag为true,则进行模式匹配选择策略。如果predicateFlag为false,则直接根据 mark 查询策略。

  • chooseAndExecute(String mark, REQUEST requestParam)

    根据标识选择策略并执行,调用对应的execute方法。

  • chooseAndExecute(String mark, REQUEST requestParam, Boolean predicateFlag):根据标识和模式匹配标识选择策略并执行。

  • onApplicationEvent(ApplicationInitializingEvent event):实现ApplicationListener接口,当Spring应用初始化时,自动注册所有的AbstractExecuteStrategy实现类

3.4 具体策略实现类

@Component
public class AddStrategy  implements AbstractExecuteStrategy<Integer, Integer> {
    @Override
    public String mark() {
        return "ADD";
    }

    @Override
    public Integer executeResp(Integer requestParam) {
        return requestParam + 10; // 假设每次加10
    }

}

3.5 测试

@SpringBootTest
class StrategyPatternApplicationTests {

    @Autowired
    private AbstractStrategyChoose strategyChoose;

    @Test
    void testAddStrategy() {
        // 测试加法策略
        Integer addResult = strategyChoose.chooseAndExecuteResp("ADD", 20);
        System.out.println("Add Strategy Result: " + addResult); // 期望结果:30
        assertEquals(Integer.valueOf(30), addResult);
    }
}

参考资料

Java设计模式之策略模式(UML类图分析+代码详解)

12306: 完成高仿铁路 12306 用户 + 抢票 + 订单 + 支付服务


http://www.kler.cn/a/376691.html

相关文章:

  • 二、应用层,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》
  • 【日志】初学顺序表
  • 基于springboot+vue实现的任务管理系统(源码+L文)4-103
  • 基于物联网的户外环境检测装置教学文章
  • SICTF Round #4|MISC
  • 在VSCode中读取Markdown文件
  • Java使用apache.commons.io框架下的FileUtils类实现文件的写入、读取、复制、删除
  • Git 使用指南:从基础到实战
  • 机器人领域中的scaling law:通过复现斯坦福机器人UMI——探讨数据规模化定律(含UMI的复现关键)
  • 【Seed-Labs】SQL Injection Attack Lab
  • 1231243545347ikih
  • nginx代理websocket服务
  • 基于单片机的单键智能密码锁设计
  • “七巨头”(The Magnificent 7)科技公司财报喜忧参半看AI
  • 长短期记忆网络(LSTM)如何在连续的时间步骤中处理信息
  • SQL中的IN语句和EXISTS语句
  • TSO(Timestamp Oracle,时间戳预言机)概念简述
  • 【Python · Pytorch】人工神经网络 ANN(上)
  • GA/T1400视图库平台EasyCVR视频分析设备平台微信H5小程序:智能视频监控的新篇章
  • R使用ggplot实现基础数据可视化
  • Python 标准库——argparse模块
  • 【设计模式】如何用C++实现依赖倒置
  • 人工智能技术:塑造未来生活与工作的变革力量
  • 【机器学习】K-means 聚类
  • C++——二叉树(进阶)
  • STM32(hal库)中,系统滴答时钟(Systick)频繁进入中断(默认1ms一次),是否会频繁进入中断,影响主程序的运行?