【23种设计模式】策略模式(State Pattern)

news2025/1/31 2:51:20

个人主页:金鳞踏雨

个人简介:大家好,我是金鳞,一个初出茅庐的Java小白

目前状况:22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作

我的博客:这里是CSDN,是我学习技术,总结知识的地方。希望和各位大佬交流,共同进步 ~

策略模式概念

策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时根据不同的情况选择不同的算法或策略,以解决相似问题的不同变体。它可以以相同的方式调用所有的算法,减少了各种算法类使用类之间的耦合

核心思想是将算法封装成独立的策略类,使得它们可以互相替换,从而使得上下文类在运行时可以选择不同的策略来执行特定的操作。

这种灵活性使得系统更易于扩展和维护,同时也可以根据不同的需求选择最合适的算法。

简单来说,就是为了解决多重 if 的问题,优化代码结构

策略模式角色

策略设计模式中,通常涉及以下几个角色

  1. 环境(Context)/ 上下文:环境是策略模式的核心,它持有一个策略对象的引用,并在需要执行特定算法时,调用策略对象的方法。环境类负责将客户端的请求委派给具体的策略对象。

  2. 抽象策略(Strategy):抽象策略定义了策略类的公共接口,它可以是一个接口或抽象类。它声明了策略类应该实现的方法,以便环境类能够通过统一的接口调用不同的策略。

  3. 具体策略(Concrete Strategy):具体策略是抽象策略的具体实现,它实现了策略接口定义的方法,并封装了具体的算法逻辑。在不同的具体策略中,算法的实现可以有所不同。

策略模式代码实现

案例一:多种排序方式选择

常见的排序算法有8种,在一些特定的场景,性能可能差别很大,所以我们需要选择一种策略。

抽象策略-接口

// 抽象策略接口
public interface SortingStrategy {
    void sort(int[] array);
}

首先,我们定义了一个抽象策略接口 SortingStrategy,其中声明了一个 sort() 方法,用于对整数数组进行排序。

2个具体策略

// 具体策略类1:冒泡排序
public class BubbleSortStrategy implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // 冒泡排序算法实现
    }
}

// 具体策略类2:快速排序
public class QuickSortStrategy implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // 快速排序算法实现
    }
}

然后,我们实现了两个具体策略类 BubbleSortStrategy QuickSortStrategy ,它们分别实现了 SortingStrategy 接口,并分别实现了冒泡排序和快速排序算法的具体排序逻辑。

环境(Context)/ 上下文 

// 环境/上下文 类
public class SortContext {
    private SortingStrategy strategy;

    public SortContext(SortingStrategy strategy) {
        this.strategy = strategy;
    }

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

    public void performSort(int[] array) {
        strategy.sort(array);
    }
}

接下来,我们定义了一个环境类 SortContext,它持有一个 SortingStrategy 类型的策略对象。构造函数接受一个策略对象作为参数,并提供了 setStrategy() 方法,用于在运行时切换策略。 方法 performSort() 用于执行排序操作,它将排序任务委托给当前策略对象。

// 使用示例
public class StrategyExample {
    public static void main(String[] args) {
        int[] array = {5, 2, 8, 1, 9};

        SortContext context = new SortContext(new BubbleSortStrategy());
        context.performSort(array); // 使用冒泡排序算法

        context.setStrategy(new QuickSortStrategy());
        context.performSort(array); // 使用快速排序算法
    }
}

最后,在 StrategyExample 类的 main 方法中,我们创建了一个整数数组 array ,然后创建了一个 SortContext 对象,并初始化它使用冒泡排序策略。我们调用 performSort() 方法来执行排序操作,使用冒泡排序算法对数组进行排序。

接着,我们通过调用 setStrategy() 方法将策略切换为快速排序策略,并再次调用performSort() 方法来使用快速排序算法对数组进行排序。

案例二:聚合支付平台-余胜军课程示例代码

搭建聚合支付平台的时候,这时候需要对接很多第三方支付接口,比如支付宝、微信支付、小米支付等等。

通过传统if代码判断的,后期的维护性非常差!

public  String toPayHtml2(String payCode){
    if(payCode.equals("ali_pay")){
        return  "调用支付宝接口...";
    }
    if(payCode.equals("xiaomi_pay")){
        return  "调用小米支付接口";
    }
    if(payCode.equals("yinlian_pay")){
        return  "调用银联支付接口...";
    }
    return  "未找到该接口...";
}

这时候可以通过策略模式解决多重if判断问题。 

抽象策略-接口

/**
 * 抽象策略-接口
 */
public interface PayStrategy {
    String toPayHtml();
}

具体策略-阿里支付、银联支付

/**
 * 具体策略-阿里支付
 */
@Component
public class AliPayStrategy  implements PayStrategy {
    public String toPayHtml() {
        return "调用支付宝支付接口";
    }
}

/**
 * 具体策略-银联支付
 */
@Component
public class UnionPayStrategy implements PayStrategy {
    public String toPayHtml() {
        return "调用银联支付接口";
    }
}

枚举支付方式

public enum PayEnumStrategy {

    /**
     * 支付宝支付
     */
    ALI_PAY("com.harmony.strategy_pay.impl.AliPayStrategy"),
    /**
     *  银联支付
     */
    UNION_PAY("com.mayikt.strategy.impl.UnionPayStrategy");

    /**
     * class完整地址
     */
    private String className;

    PayEnumStrategy(String className) {
        this.setClassName(className);
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }
}

环境(Context)/ 上下文

@Component
public class PayContextStrategy {

    public  String toPayHtml(String payCode){
        // 1.验证参数
        if(StringUtils.isEmpty(payCode)){
            return  "payCode不能为空!";
        }

        // 2.获取
        PayStrategy payStrategy = StrategyFactory.getPayStrategy(payCode);
        if(payStrategy == null) {
            return "没有找到具体的策略...";
        }

        return payStrategy.toPayHtml();
    }
}

工厂类 

public class StrategyFactory {
    public static PayStrategy getPayStrategy(String strategyType) {
        try {
            // 1.获取枚举中className
            String className = PayEnumStrategy.valueOf(strategyType).getClassName();
            // 2.使用java反射技术初始化类
            return (PayStrategy) Class.forName(className).newInstance();
        } catch (Exception e) {
            return null;
        }
    }
}

使用SpringBoot的方式调用

/**
 * 启动类
 */
@SpringBootApplication
public class AppStart {
    public static void main(String[] args) {
        SpringApplication.run(AppStart.class);
    }
}

/**
 * controller
 * http://localhost:8080/toPayHtml?payCode=ALI_PAY
 */
@RestController
public class PayController {

    @Autowired
    private PayContextStrategy payContextStrategy;

    @RequestMapping("/toPayHtml")
    public String toPayHtml(String payCode) {
        return payContextStrategy.toPayHtml(payCode);
    }
}

文章到这里就结束了,如果有什么疑问的地方,可以在评论区指出~

希望能和大佬们一起努力,诸君顶峰相见

再次感谢各位小伙伴儿们的支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/631796.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 Python Selenium 提取动态生成下拉选项

在进行网络数据采集和数据分析时,处理动态生成的下拉菜单是一个常见的挑战。Selenium是一个强大的Python库,可以让你自动化浏览器操作,比如从动态生成的下拉菜单中选择选项。这是一个常见的网页爬虫和数据收集者面临的挑战,但是Se…

C#可视化 家用轿车信息查询系统(具体做法及全部代码)

目录 题目: 效果图: 数据库: 做法: combobox值更新 查询按钮功能(非空验证,查询数据) datagirdview设置 全部代码: DBHelper类 From1主窗体代码 题目: 效果图&#…

Qt Button实现按钮长按事件

Qt Button实现按钮长按事件 背景查资料第3种widget.cpp源文件 最好方法小结 背景 最近项目遇到一个需求,通过鼠标按钮长按一直发数据,鼠标松开立即离开。 想了一会儿大概有了几种思路(仅仅是思路,不一样可以实现) 1.重…

OBS Studio 29.1.2 正式发布

导读OBS Studio 是一款免费且开源的用于视频录制以及直播串流的软件,提供实时高性能的视频 / 音频捕捉与混合,以及无限的场景模式帮助用户通过自定义实现无缝转换。 OBS Studio 29.1.2 现已发布,具体更新内容包括: 在 Windows 设…

[7]PCB设计实验|认识常用元器件|电容器|19:00~19:30

目录 一、电容器的识别 电容的应用 1. 电容有通交流阻隔直流电的作用 2. 有滤波、耦合、旁路作用等 3. 有些电容是有极性,有些是没有极性 二、常见电容器 1. 贴片电容 a、材质瓷片 b、材质钽介质 c、材质电解质 2. 手插电容 a、瓷片电容 b、聚脂电容 …

【计算机组成与体系结构Ⅰ】课程设计——基于Logisim的模型计算机设计

基于Logisim的模型计算机设计 一、实验目的 基于Logisim软件,根据一个模型指令系统,在逐步学习和了解计算机组成各部分逻辑组成和各部分互联的基础上,深入理解课程中的知识点,利用此软件设计并实现一个模拟的8位模型计算机原型。…

NumPy库的学习

本文主要记录的是笔者在B站自学Numpy库的学习笔记。 引入numpy库 import numpy as np矩阵的创建 创建一个二行三列的矩阵。 array np.array([[1,2,3],[2,3,4]])查看array的行数、形状、元素数量 print("number of dim:",array.ndim) print("shape:"…

Sui x KuCoin Labs夏季黑客松|6月8日Suiet Workshop

由Sui和KuCoin Labs联合主办的夏季黑客松正如火如荼的报名中。了解黑客松详情:Sui与KuCoin Labs联合推出夏季黑客松,奖池高达28.5万美金! 👉 黑客松官方网站:Sui x KuCoin Labs Summer Hackathon 活动期间&#xff0…

2023年前端面试汇总-CSS

1. CSS基础 1.1. CSS选择器及其优先级 对于选择器的优先级: 1. 标签选择器、伪元素选择器:1; 2. 类选择器、伪类选择器、属性选择器:10; 3. id 选择器:100; 4. 内联样式:1000&a…

基于BP神经网络对MNIST数据集检测识别(numpy版本)

基于BP神经网络对MNIST数据集检测识别 1.作者介绍2.BP神经网络介绍2.1 BP神经网络 3.BP神经网络对MNIST数据集检测实验3.1 读取数据集3.2 前向传播3.3 损失函数3.4 构建神经网络3.5 训练3.6 模型推理 4.完整代码 1.作者…

EasyX实现简易贪吃蛇

📝个人主页:认真写博客的夏目浅石. 📣系列专栏:夏目的C语言宝藏 文章目录 前言一、头文件包含二、创建蛇与食物的结构体三、游戏的初始化四、游戏的绘画事件五、蛇的移动事件六、输入方向七、生成食物八、吃食物九、游戏失败的判定…

【Python开发】FastAPI 09:middleware 中间件及跨域

FastAPI 提供了一些中间件来增强它的功能,类似于 Spring 的切面编程,中间件可以在请求处理前或处理后执行一些操作,例如记录日志、添加请求头、鉴权等,跨域也是 FastAPI 中间件的一部分。 目录 1 中间件 1.1 创建中间件 1.2 使…

IDEA日常配置和操作小结

✅作者简介:大家好,我是Cisyam,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Cisyam-Shark的博客 💞当前专栏: IDEA专栏 ✨特色专栏&…

算法刷题-数组-长度最小的子数组

209.长度最小的子数组 力扣题目链接 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。 示例: 输入:s 7, …

电子元器件解析之电容(一)——定义与性能参数

下篇文章:电子元器件解析之电容(二)——电容分类与应用场景:https://blog.csdn.net/weixin_42837669/article/details/131142767 摘要 电容是最基本的电子元器件之一,本文介绍了电容的定义,并总结了电容的各个性能参数&#xff0c…

攻防世界—easyupload

2023.6.10 又试了一下 他好像会检测php字段,所以一开始的aaa.jpg怎么也传不上去,用a.jpg那种就可以了 根据题目和页面我们可以猜到这应该是一个利用文件上传漏洞,利用一句话木马来获取服务器上保存的flag保险起见右键查看源代码 可以发现毫无…

基础实验篇 | RflySim底层飞行控制算法开发系列课程总体介绍

本讲主要介绍多旋翼的特点及选用多旋翼作为实验平台的原因、对于无人系统教育的一些新需求、RflySim平台对于飞控的底层控制算法的开发优势、本期平台课程的设置、以及如何开发自驾仪系统。 相较于固定翼和直升机,多旋翼具有机械结构简单、 易维护的优点。以四旋翼…

使用 Pycharm 调试远程代码

文章目录 背景同步远程代码Interpreter注意点 背景 工作机是一台 Windows 电脑,而很多时候需要在 Mac 电脑上编码、配合 iPhone 模拟器,所以我以前是用 VNC 或者向日葵来远程 Mac 来编程,其实还能接受,但是最让我不舒服的是快捷键…

MySQL表操作:提高数据处理效率的秘诀(进阶)(2)

💕“学习难免有坎坷,重要的是你能尽力而为,持之以恒。”💕 🐼作者:不能再留遗憾了🐼 🎆专栏:MySQL学习🎆 🚗本文章主要内容:MySQL表操…

K Shortest Paths算法之Yen algorithm

Yen’s算法是一种在图论中用于计算单源K最短无环路径的算法,该算法由Jin Y. Yen在1971年提出。这个算法的时间复杂度和空间复杂度都取决于用于计算偏离路径的最短路径算法。如果使用Dijkstra算法,那么时间复杂度为O(KN3),采用Fibonacci堆计算…