前言:

现在电商已经成为我们生活中不可或缺的购物渠道,同时各大商家会针对不同的时间做出不同的折扣,这在我们看来就是一种营销手段,也是一种策略,今天我们就来讲讲JDK中的策略模式是怎么样的。

一、定义

  定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。可以用来消除大量的if...else结构。

二、适用场景

 1、系统有很多类,它们的区别仅在于它们的行为不同

 2、一个系统需要动态的在几种算法中选择一种

  在这里稍微理解一下,策略模式其实和工厂模式很像,不过工厂模式是创建型的,是接收到指令来去创建相应的工厂,而策略模式是传入一个创建好的策略来实现具体行为。重点理解行为和算法。其实只不过是我们根据不同业务场景做出的不同反应,拿淘宝来说,双十一的促销活动力度最大,可能打到5折,而女王节一般只打到7折。针对这两种不同的对象,就有两种不同的行为或者不同的算法,在客户端调用时,可以直接传入对应的策略就能做出相应的行为。下面我们来具体看一下策略模式在JDK中的应用

三、Comparator中的策略模式

  我们先来认清,策略模式中到底需要什么角色:

    1、抽象策略角色

      负责定义通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

    2、策略实现类

      不同的类实现具体不同的算法。

    3、环境角色类

      里面持有抽象策略角色的引用,然后客户端可以由具体的方法传不同参数或实现类进去得到不同算法。

  我们现在直接看Arrays这个类

public class Arrays{public static <T> void sort(T[] a, Comparator<? super T> c) {if (c == null) {sort(a);} else {if (LegacyMergeSort.userRequested)legacyMergeSort(a, c);elseTimSort.sort(a, 0, a.length, c, null, 0, 0);}}
}

  Arrays就是一个环境角色类,这个sort方法你可以传一个新策略让Arrays根据这个方法来进行排序。就比如下面的测试类。

public class Test1 {public static void main(String[] args) {Integer []data ={12,2,3,2,4,5,1};
// 实现降序排序,返回-1放左边,1放右边,0保持不变Arrays.sort(data, (str1, str2) -> {if (str1.compareTo(str2) > 0) {return -1;} else {return 1;}});System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]
    }
}

  这里是直接用lambda表达式进行重写Comparator接口中的compare方法,可以认为这里的lambda表达式就是具体的算法,可见Comparator充当的就是抽象策略角色。我上面说过,环境角色类应该持有抽象策略的引用来调用,Arrays类中的sort方法是直接传Comparator接口,如果是有自己的compare方法那么就会进入到下面这个方法

class TimSort<T> {static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,T[] work, int workBase, int workLen) {assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;int nRemaining  = hi - lo;if (nRemaining < 2)return;  // Arrays of size 0 and 1 are always sorted// If array is small, do a "mini-TimSort" with no mergesif (nRemaining < MIN_MERGE) {int initRunLen = countRunAndMakeAscending(a, lo, hi, c);binarySort(a, lo, hi, lo + initRunLen, c);return;}private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,Comparator<? super T> c) {assert lo < hi;int runHi = lo + 1;if (runHi == hi)return 1;// Find end of run, and reverse range if descendingif (c.compare(a[runHi++], a[lo]) < 0) { // Descendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)runHi++;reverseRange(a, lo, runHi);} else {                              // Ascendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)runHi++;}return runHi - lo;}
}

  这里多说一下,上面的代码中最终会跑到countRunAndMakeAscending这个方法中。我们可以看见,只用了compare方法,所以在调用Arrays.sort方法只传具体compare重写方法的类就行,这也是Comparator接口中必须要子类实现的一个方法。

四、总结

  其实学了这么多模式,你会发现这些模式的大体很相似,但是细究起来又不相似。策略模式是很容易和工厂模式弄混淆的。策略模式的核心就是不同的行为对应不同的算法,而工厂更多的是生产不同的产品,给产品规定好的参数和返回类型。

转载于:https://www.cnblogs.com/Cubemen/p/10698268.html

结合JDK源码看设计模式——策略模式相关推荐

  1. 结合JDK源码看设计模式——桥接模式

    前言: 在我们还没学习框架之前,肯定都学过JDBC.百度百科对JDBC是这样介绍的[JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Jav ...

  2. 结合JDK源码看设计模式——简单工厂、工厂方法、抽象工厂

    三种工厂模式的详解: 简单工厂模式: 适用场景:工厂类负责创建的对象较少,客户端只关心传入工厂类的参数,对于如何创建对象的逻辑不关心 缺点:如果要新加产品,就需要修改工厂类的判断逻辑,违背软件设计中的 ...

  3. 从JDK源码看关闭钩子

    关闭钩子 Java提供了Shutdown Hook机制,它让我们在程序正常退出或者发生异常时能有机会做一些清场工作.使用的方法也很简单,Java.Runtime.addShutdownHook(Thr ...

  4. Android源码看设计模式(十)--------关于享元模式的Handler相关分析

    享元模式 定义: 使用共享对象可以有效的支持大量的细粒度的对象 应用场景 系统中存在大量的相似对象 细粒度的对象都具备比较接近的外部状态,而内部状态与环境无关,也就是说对象没有特定身份 需要缓冲池的场 ...

  5. 设计模式--spring源码中使用策略模式(Strategy Pattern)

    转载http://liuxi1024.iteye.com/blog/583145 策略模式(Strategy Pattern)中体现了两个非常基本的面向对象设计的基本原则:封装变化的概念:编程中使用接 ...

  6. 王者荣耀java实现_从王者荣耀看设计模式-策略模式(java版)

    王者荣耀 曾经我也是一名玩农药的大学生,但现在已经弃了,别问我为什么(被坑爹队友坑的哭...).而今天我们来把让农药变荣耀,我们来从王者荣耀中看设计模式的策略模式. 射手 00.分析 我们先来思考,王 ...

  7. Android源码看设计模式(十二)--------关于观察者模式的Rxjava的相关分析

    观察者模式 定义: 定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并且被自动更新 使用场景 关联行为场景,注意不是"组合"关系 事件多级 ...

  8. jdk源码分析书籍 pdf_如何阅读源码?

    点击上方"IT牧场",选择"设为星标" 技术干货每日送达! 阅读源码是每个优秀开发工程师的必经之路,那么这篇文章就来讲解下为什么要阅读源码以及如何阅读源码. 首 ...

  9. java int类源码,一起学JDK源码 -- Integer类

    Integer类为java基本类型int的包装类,除了前面提到的Byte类,Short类中的大部分方法,Integer类中还提供了很多处理int类型的方法,接下来就让我们一起看看吧. 基础知识: 1. ...

最新文章

  1. 影响网站快照异常的因素有哪些?
  2. C/C++训练1---最大公约数与最小公倍数_JAVA
  3. 二叉树的最大深度—leetcode104
  4. mysql7.5安装教程_CentOS7.5下yum安装MySQL8图文教程
  5. 【公众号系列】SAP的新零售
  6. dev gridcontrol 单箱效果
  7. GsonFormat插件使用
  8. 最近这里了这几年做过的计算机专业毕业设计题目如下:
  9. 【小程序项目分享】多功能抽签分组系统
  10. 使用pr给视频局部打马赛克
  11. 数据分析指标到底应该怎么解读?
  12. 【转】人不成熟的几大特征——海尔集团CEO张瑞敏演讲稿
  13. kali之永恒之蓝使用流程(操作全套步骤)
  14. Navicat快捷键选择当前行
  15. 浅谈数据中心综合布线运维管理方式发展史
  16. 苹果产品信息查询_苹果维修召回计划 + iPhone辨别真伪
  17. OWASP TOP 10-2021年十大Web应用安全风险榜单
  18. Python|面向对象编程的类和实例
  19. LintCode-买卖股票的最佳时机
  20. 甲骨文业绩超预期股价大涨近11% 市值首超2000亿美元

热门文章

  1. 《JS权威指南学习总结--1.1语言核心》
  2. reposurgeon 2.15 发布
  3. 判断字符串是不是数字
  4. jiebaR中文分词,从入门到喜欢
  5. php file_get_contents 临时目录 fopen,php fopen()和file_get_contents() 区别介绍
  6. cin输入字符串怎么结束_翻遍全网,只为让你记住这些输入输出函数
  7. 解析列表中的数据python_将html数据解析成python列表进行操作
  8. mqtt 串口_MQTT网关介绍及应用原理
  9. yii 执行指定迁移文件_Web 云开发 · 云开发数据库迁移指南
  10. python整数池_【Python】Python中神奇的小整数对象池和大整数对象池