策略模式原来就这么简单!

别再死记硬背了!用Amesim HCD库亲手搭建单向阀、锥阀、球阀模型(附详细参数设置) 本文详细介绍了如何使用Amesim HCD库从零构建单向阀、锥阀和球阀的仿真模型,帮助工程师摆脱死记硬背,掌握物理建模的核心技巧。通过实战案例和参数设置指南,读者将学会如何优化阀门动态响应、验证流量特性以及处理旋转运动等独特挑战,提升液压系统设计效率。 阅读详情

前言

只有光头才能变强

回顾前面:

无论是面试还是个人的提升,设计模式是必学的。今天来讲解策略模式~

一、策略模式介绍

我一次听到策略模式这个词,是在我初学JDBC的时候。不知道大家有没有用过DBUtils这个组件。当时初学跟着视频学习,方立勋老师首先是让我们先自己封装一下JDBC的一些常用的操作(实际上就是模仿DBUtils这个组件)。

当时候的问题是这样的:我们打算封装一下 query()查询方法,传入的参数有 Stringsql,Object[]objects(指定SQL语句和对应的参数)。我们想根据不同的业务返回不同的值。

  • 比如说,有的时候我们返回的是一条数据,那我们想将这条数据封装成一个Bean对象

  • 比如说,有的时候我们返回的是多条数据,那我们想将这多条数据封装成一个 List<Bean> 集合

  • 比如说,有的时候我们返回的是xxxx数据,那我们想将这多条数据封装成一个 Map<Bean> 集合

  • ........等等等

当时解决方案是这样的:

  • 先定义一个接口:ResultSetHandler(调用者想要对结果集进行什么操作,只要实现这个接口即可)

    • 这个接口定义了行为。 Objecthanlder(ResultSetresultSet);

  • 然后实现上面的接口,比如我们要封装成一个Bean对象,就是 publicclassBeanHandlerimplementsResultSetHandler

  • 调用的时候,实际上就是 query()查询方法多一个参数 query(Stringsql,Object[]objects,ResultSetHandlerrsh)。调用者想要返回什么类型,只要传入相对应的ResultSetHandler实现类就是了。

代码如下:

    query方法:	
    //这个方法的返回值是任意类型的,所以定义为Object。	
    public static Object query(String sql, Object[] objects, ResultSetHandler rsh) {	
        Connection connection = null;	
        PreparedStatement preparedStatement = null;	
        ResultSet resultSet = null;	
        try {	
            connection = getConnection();	
            preparedStatement = connection.prepareStatement(sql);	
            //根据传递进来的参数,设置SQL占位符的值	
            if (objects != null) {	
                for (int i = 0; i < objects.length; i++) {	
                    preparedStatement.setObject(i + 1, objects[i]);	
                }	
            }	
            resultSet = preparedStatement.executeQuery();	
            //调用调用者传递进来实现类的方法,对结果集进行操作	
            return rsh.hanlder(resultSet);	
    }	
    接口:	
    /*	
    * 定义对结果集操作的接口,调用者想要对结果集进行什么操作,只要实现这个接口即可	
    * */	
    public interface ResultSetHandler {	
         Object hanlder(ResultSet resultSet);	
    }	
    接口实现类(Example):	
    //接口实现类,对结果集封装成一个Bean对象	
    public class BeanHandler implements ResultSetHandler {	
        //要封装成一个Bean对象,首先要知道Bean是什么,这个也是调用者传递进来的。	
        private Class clazz;	
        public BeanHandler(Class clazz) {	
            this.clazz = clazz;	
        }	
        @Override	
        public Object hanlder(ResultSet resultSet) {	
            try {	
                //创建传进对象的实例化	
                Object bean = clazz.newInstance();	
                if (resultSet.next()) {	
                    //拿到结果集元数据	
                    ResultSetMetaData resultSetMetaData = resultSet.getMetaData();	
                    for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) {	
                        //获取到每列的列名	
                        String columnName = resultSetMetaData.getColumnName(i+1);	
                        //获取到每列的数据	
                        String columnData = resultSet.getString(i+1);	
                        //设置Bean属性	
                        Field field = clazz.getDeclaredField(columnName);	
                        field.setAccessible(true);	
                        field.set(bean,columnData);	
                    }	
                    //返回Bean对象	
                    return bean;	
                }

这就是策略模式??就这??这不是多态的使用吗??

1.1策略模式讲解

《设计模式之禅》:

定义一组算法,将每个算法都封装起来,并且使他们之间可以互换

策略模式的类图是这样的:

640

策略的接口和具体的实现应该很好理解:

  • 策略的接口相当于我们上面所讲的ResultSetHandler接口(定义了策略的行为)

  • 具体的实现相当于我们上面所讲的BeanHandler实现(接口的具体实现)

    • 具体的实现一般还会有几个,比如可能还有ListBeanHandler、MapBeanHandler等等

令人想不明白的可能是:策略模式还有一个Context上下文对象。这对象是用来干什么的呢?

《设计模式之禅》:

Context叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。

在知乎上也有类似的问题(为什么不直接调用,而要通过Person?):

640

说白了,通过Person来调用更符合面向对象(屏蔽了直接对具体实现的访问)。

首先要明白一个道理,就是——到底是 “人” 旅游,还是火车、汽车、自行车、飞机这些交通工具旅游?

如果没有上下文的话,客户端就必须直接和具体的策略实现进行交互了,尤其是需要提供一些公共功能或者是存储一些状态的时候,会大大增加客户端使用的难度;引入上下文之后,这部分工作可以由上下文来完成,客户端只需要和上下文进行交互就可以了。这样可以让策略模式更具有整体性,客户端也更加的简单

具体的链接:

  • https://www.zhihu.com/question/31162942

所以我们再说回上文的通用类图,我们就可以这样看了:

640

1.2策略模式例子

现在3y拥有一个公众号,名称叫做Java3y。3y想要这让更多的人认识到Java3y这个公众号。所以每天都在想怎么涨粉(hahah

于是3y就开始想办法了(操碎了心),同时3y在这一段时间下来发现涨粉的方式有很多。为了方便,定义一个通用的接口方便来管理和使用呗。

接口:

/**	
 * 增加粉丝策略的接口(Strategy)	
 */	
interface IncreaseFansStrategy {	
    void action();	
}

涨粉的具体措施,比如说,请水军:

/**	
 * 请水军(ConcreteStrategy)	
 */	
public class WaterArmy implements IncreaseFansStrategy {	
    @Override	
    public void action() {	
        System.out.println("3y牛逼,我要给你点赞、转发、加鸡腿!");	
    }	
}

涨粉的具体措施,比如说,认真写原创:

/**	
 * 认真写原创(ConcreteStrategy)	
 */	
public class OriginalArticle implements IncreaseFansStrategy{	
    @Override	
    public void action() {	
        System.out.println("3y认真写原创,最新一篇文章:《策略模式,就这?》");	
    }	
}

3y还想到了很多涨粉的方法,比如说送书活动啊、商业互吹啊等等等...(这里就不细说了)

说到底,无论是哪种涨粉方法,都是通过3y去执行的。

/**	
 * 3y(Context)	
 */	
public class Java3y {	
    private IncreaseFansStrategy strategy ;	
    public Java3y(IncreaseFansStrategy strategy) {	
        this.strategy = strategy;	
    }	
    // 3y要发文章了(买水军了、送书了、写知乎引流了...)。	
    // 具体执行哪个,看3y选哪个	
    public void exec() {	
        strategy.action();	
    }	
}

所以啊,每当到了发推文的时候,3y就可以挑用哪种方式涨粉了:

public class Main {	
    public static void main(String[] args) {	
        // 今天2018年12月24日	
        Java3y java3y = new Java3y(new WaterArmy());	
        java3y.exec();	
        // 明天2018年12月25日	
        Java3y java4y = new Java3y(new OriginalArticle());	
        java4y.exec();	
        // ......	
    }	
}

执行结果:

640

1.3策略模式优缺点

优点:

  • 算法可以自由切换

    • 改一下策略很方便

  • 扩展性良好

    • 增加一个策略,就多增加一个类就好了。

缺点:

  • 策略类的数量增多

    • 每一个策略都是一个类,复用的可能性很小、类数量增多

  • 所有的策略类都需要对外暴露

    • 上层模块必须知道有哪些策略,然后才能决定使用哪一个策略

640

1.4JDK的策略模式应用

不知道大家还能不能想起ThreadPoolExecutor(线程池):线程池你真不来了解一下吗?

学习ThreadPoolExecutor(线程池)就肯定要知道它的构造方法每个参数的意义:

    /**	
     * Handler called when saturated or shutdown in execute.	
     */	
    private volatile RejectedExecutionHandler handler;	
    public ThreadPoolExecutor(int corePoolSize,	
                              int maximumPoolSize,	
                              long keepAliveTime,	
                              TimeUnit unit,	
                              BlockingQueue<Runnable> workQueue,	
                              ThreadFactory threadFactory,	
                              RejectedExecutionHandler handler) {	
        //....	
        this.handler = handler;	
    }	
    /**	
     * Invokes the rejected execution handler for the given command.	
     * Package-protected for use by ScheduledThreadPoolExecutor.	
     */	
    final void reject(Runnable command) {	
        handler.rejectedExecution(command, this);	
    }

其中我们可以找到RejectedExecutionHandler,这个参数代表的是拒绝策略(有四种具体的实现:直接抛出异常、使用调用者的线程来处理、直接丢掉这个任务、丢掉最老的任务)

其实这就是策略模式的体现了。

最后

看完会不会觉得策略模式特别简单呀?就一个算法接口、多个算法实现、一个Context来包装一下,就完事了。

推荐阅读和参考资料:

  • https://www.cnblogs.com/lewis0077/p/5133812.html

  • 《设计模式之禅》

乐于分享和输出干货的Java技术公众号:Java3y。

640

文章的目录导航:

  • https://github.com/ZhongFuCheng3y/3y


ESP8266+ITR8307实战:如何用反射式光电管实现5cm远距离检测(附避坑指南) 本文详细介绍了如何利用ESP8266的ADC功能与ITR8307反射式光电管,通过调制解调、硬件电路优化及软件同步采样策略,实现5cm稳定远距离检测。文章提供了完整的硬件设计、代码实现与调优避坑指南,有效解决了环境光干扰与信号衰减难题,适用于智能车、自动化等需要可靠非接触检测的项目。 阅读详情

相关推荐

MDT部署实战:除了Office,这些“装机必备”软件也能一键静默安装(含静默参数)

本文详细介绍了如何利用Microsoft Deployment Toolkit(MDT)实现企业级软件的静默安装,包括浏览器、开发工具和系统增强工具等“装机必备”软件的部署方案。通过命令行参数和MSI属性,IT运维团队可以高效构建标准化工作环境,提升部署效率并确保版本一致性。文章还提供了安装顺序控制、结果验证和常见问题排错等高级技巧。

weixin_26985923的博客 172

LVGL 8.3 Tabview控件使用Keypad导航

LVGL 8.3 Tabview控件使用Keypad导航

四文鱼Max的博客 2694

保姆级教程:在爱快iKuai虚拟机里装OpenWrt旁路由,实现去广告和特殊功能

本文提供在爱快iKuai虚拟机中安装OpenWrt旁路由的详细教程,帮助用户实现去广告和特殊功能扩展。通过分步指导,包括虚拟机配置、网络设置和功能优化,打造稳定高效的家庭网络环境,特别适合软路由爱好者和网络管理员。

weixin_31364787的博客 830

嵌入式GUI LVGL『Tableview选项卡控件』介绍

一. LVGL GUI开关控件的概念 选项卡视图对象可用于组织选项卡中的内容。 二. LVGL GUI开关小部件和样式 Tab 视图对象包含几个部分。主要是 LV_TABVIEW_PART_BG 。它是一个矩形容器,用于容纳 Tab 视 图的其他部分。 在背景上创建了两个重要的真实部分: LV_TABVIEW_PART_BG_SCRL :这是 Page 的可滚动部分。它使选项卡的内容彼此相邻。页面的背景始终是透明的,不能从外部访问。 LV_TABVIEW_PART_TAB_BG :选项卡按钮,它是

朝气蓬勃 6939

SpotBugs使用

spotbugs命令行参数解析

javajingling的专栏 2947

Halcon工业相机开发全流程:从SDK配置到实时图像采集(C++版)

本文详细介绍了使用C++进行Halcon工业相机开发的完整流程,从SDK配置到实时图像采集的实现。涵盖环境搭建、设备初始化、回调机制、参数控制等关键环节,并提供异常处理和实战案例,帮助开发者快速掌握工业视觉系统的开发技巧。

weixin_33728268的博客 512

C#之策略模式

策略模式定义为:定义算法家族,封装每一个算法,并使它们可以替换。策略可以让算法独立于使用它的客户端。 这个模式涉及到三个角色: 环境(Context)角色:持有一个Strategy的引用。 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。 案例展示: 在...

lisa丶 1612

[UVM]UVM TLM2.0简介及应用实例分析

本文介绍了TLM2.0在UVM中的实现与应用。TLM2.0作为SystemC模型间的核心传输机制,相比TLM1.0提供了更丰富的特性,包括双向阻塞/非阻塞接口、时间标记和统一数据包。文章详细解析了TLM2.0在UVM中的接口实现方式,包括socket类型定义、数据传输机制以及时间标记处理。通过一个具体实例,展示了如何在UVM组件中使用TLM2.0的initiator和target socket进行数据传输,并说明了标准数据包格式和精确时间标记的优势。最后指出TLM2.0在UVM中的实现主要是为了与Syste

元直的博客 5397

【C#设计模式】19.策略模式(Strategy Pattern)【行为型】

1.1 动机(Motivate) 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题? 1.2 意图(Intent) 定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。该模式使得算法可独立于使用它的客户而变化。       ——《设计模式》GoF .........

星Yeah 的博客 3687

RT-DETR改进策略【Neck】| GFPN 超越BiFPN 通过跳层连接和跨尺度连接改进RT-DETR颈部网络

本文记录的是利用颈部结构优化RT-DETR的目标检测网络模型。利用改进后的颈部网络,通过跳层连接,避免了在进行反向传播时的梯度消失问题,并且引入跨尺度连接,可以实现不同级别和层次的特征充分融合,获取足够的高层语义信息和低层空间信息交换,从而在大规模变化场景下提高检测性能。GIRAFFEDET: A HEAVY-NECK PARADIGM FOR OBJECT DETECTION-GFPN包含了上述的跳层连接(dense-link和log2nlog _{2} nlog2​n-link)以及跨尺度连接(Quee

Limiiiing的博客 2229

C#串口通信革命:RJCP.DLL.SerialPortStream实战全解析

本文介绍了如何通过RJCP.DLL.SerialPortStream库实现高性能串口通信解决方案。相比.NET自带的SerialPort类,该库提供了完全的异步非阻塞IO、动态缓冲区控制和多线程事件驱动等优势,特别适合工业自动化和物联网场景。文章详细讲解了环境搭建、核心功能对比,并通过代码示例展示了端口配置、异步通信管道搭建等关键技术。最后以Modbus RTU协议为例,演示了高级协议封装方法,为开发者提供了完整的工业级串口通信实现方案。

墨夶的博客 1874

Java23种设计模式之策略模式【普通写法以及spring中的写法】

本次文章介绍的是策略模式,并且分享一下我在项目中的写法

weixin_43246215的博客 3068

ATECC508A芯片开发笔记(三):获取508A串号、随机数源码及I2C抓包分析

ATECC508A芯片开发笔记(三):读取508A串号、获取随机数源码及I2C抓包分析 APP层函数编写及源码分析 At508_GetSernum() GetSernum抓包记录 At508_GetRandom( ) GetRandom抓包记录 经过前两章节,CryptoAuthlib库已经成功适配在代码中了,下面简单测试一下API函数,并分析下I2C通讯流程: APP层函数编写及源码分析利用li

HowieXue 薛永浩的博客 2万+

原来使用 Spring 实现策略模式可以这么简单!

策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法,可以替代代码中大量的 if-else。比如我们生活中的场景:买东西结账可以使用微信支付、支付宝...

武培轩 8462

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

策略模式原来这么简单!

前言 只有光头才能变强 回顾前面: 给女朋友讲解什么是代理模式 包装模式就是这么简单啦 单例模式你会几种写法? 工厂模式理解了没有? 无论是面试还是个人的提升,设计模式是必学的。今天来讲解策略模式~ 一、策略模式介绍 我一次听到策略模式这个词,是在我初学JDBC的时候。不知道大家有没有用过DBUtils这个组件。当时初学跟着视频学习,方立勋老师首先是让我们先自己封装一下JDBC的一些常用的...

3y 584

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

别只知道策略模式+简单工厂,试试更香的策略模式+抽象工厂!

我的相关博文 三种工厂模式详解购优惠 www.fenfaw.cn 策略模式 在GOF的《设计模式:可复用面向对象软件的基础》一书中对策略模式是这样说的: 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而变化。 策略模式为了适应不同的需求,只把变化点封装了,这个变化点就是实现不同需求的算法,例如加班工资,不同的加班情况,有不同的计算加班工资的方法。 我们不能在程序中将计算工资的算法进行硬编码,而能够自由变化。 这就是策略模式。 ...

nidongla的博客 234

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: 最常用的经典数据结构和算法汇总
下一篇: 为什么阿里巴巴禁止工程师直接使用日志系统(Log4j、Logback)中的 API
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值