策略模式 喜欢ヅ旅行 2021-07-24 15:30 304阅读 0赞 # 一 点睛 # 先看下面的图片,我们去旅游选择出行模式有很多种,可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70] 作为一个程序猿,开发需要选择一款开发工具,当然可以进行代码开发的工具有很多,可以选择Idea进行开发,也可以使用eclipse进行开发,也可以使用其他的一些开发工具。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70 1] **定义:** 该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。 # 二 结构 # 策略模式的主要角色如下: * 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。 * 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。 * 环境(Context)类:持有一个策略类的引用,最终给客户端调用。 # 三 实战 # 【例】促销活动 一家百货公司在定年度的促销活动。针对不同的节日(春节、中秋节、圣诞节)推出不同的促销活动,由促销员将促销活动展示给客户。类图如下: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70 2] 代码如下 定义百货公司所有促销活动的共同接口 public interface Strategy { void show(); } 定义具体策略角色(Concrete Strategy):每个节日具体的促销活动 //为春节准备的促销活动A public class StrategyA implements Strategy { public void show() { System.out.println("买一送一"); } } //为中秋准备的促销活动B public class StrategyB implements Strategy { public void show() { System.out.println("满200元减50元"); } } //为圣诞准备的促销活动C public class StrategyC implements Strategy { public void show() { System.out.println("满1000元加一元换购任意200元以下商品"); } } 定义环境角色(Context):用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员 public class SalesMan { //持有抽象策略角色的引用 private Strategy strategy; public SalesMan(Strategy strategy) { this.strategy = strategy; } //向客户展示促销活动 public void salesManShow(){ strategy.show(); } } 测试类 public class Client { public static void main(String[] args) { // 春节来了,使用春节促销活动 SalesMan salesMan = new SalesMan(new StrategyA()); // 展示促销活动 salesMan.salesManShow(); System.out.println("=============="); // 中秋节到了,使用中秋节的促销活动 salesMan.setStrategy(new StrategyB()); // 展示促销活动 salesMan.salesManShow(); System.out.println("=============="); // 圣诞节到了,使用圣诞节的促销活动 salesMan.setStrategy(new StrategyC()); // 展示促销活动 salesMan.salesManShow(); } } # 四 测试结果 # 买一送一 ============== 满200元减50元 ============== 满1000元加一元换购任意200元以下商品 # 五 优缺点 # **优点** * 策略类之间可以自由切换 由于策略类都实现同一个接口,所以使它们之间可以自由切换。 * 易于扩展 增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“ * 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。 **缺点** * 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。 * 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。 # 六 使用场景 # * 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。 * 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。 * 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。 * 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。 * 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。 # 七 JDK源码解析 # `Comparator` 中的策略模式。在Arrays类中有一个 `sort()` 方法,如下: 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); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } } } Arrays就是一个环境角色类,这个sort方法可以传一个新策略让Arrays根据这个策略来进行排序。就比如下面的测试类。 public class demo { public static void main(String[] args) { Integer[] data = { 12, 2, 3, 2, 4, 5, 1}; // 实现降序排序 Arrays.sort(data, new Comparator<Integer>() { public int compare(Integer o1, Integer o2) { return o2 - o1; } }); System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1] } } 这里我们在调用Arrays的sort方法时,第二个参数传递的是Comparator接口的子实现类对象。所以Comparator充当的是抽象策略角色,而具体的子实现类充当的是具体策略角色。环境角色类(Arrays)应该持有抽象策略的引用来调用。那么,Arrays类的sort方法到底有没有使用Comparator子实现类中的 `compare()` 方法吗?让我们继续查看TimSort类的 `sort()` 方法,代码如下: 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 merges if (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 descending if (c.compare(a[runHi++], a[lo]) < 0) { // Descending while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0) runHi++; reverseRange(a, lo, runHi); } else { // Ascending while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0) runHi++; } return runHi - lo; } } 上面的代码中最终会跑到 `countRunAndMakeAscending()` 这个方法中。我们可以看见,只用了compare方法,所以在调用Arrays.sort方法只传具体compare重写方法的类对象就行,这也是Comparator接口中必须要子类实现的一个方法。 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70]: /images/20210724/a0c881093fd04bba8a5b93d06892c0e7.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70 1]: /images/20210724/cb62304cf62741338b14396b20feed8f.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5ncWl1bWluZw_size_16_color_FFFFFF_t_70 2]: /images/20210724/f15db28bc6cc43eca752549ca4a4b257.png
相关 策略模式 1. 定义 > 定义一系列算法,把他们一个个封装起来,并且使他们可以互相替换。本模式使得算法 > 可以独立于使用它的客户而变化。 2. 策略模式的结构 ![策 川长思鸟来/ 2022年05月29日 04:09/ 0 赞/ 60 阅读
相关 策略模式 前言 1、面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同的属性和功能的对象的抽象集合才是类。 2、简单工厂也能解决问题,但是 港控/mmm°/ 2021年12月08日 16:21/ 0 赞/ 319 阅读
相关 策略模式 用了也不知道用了的典型。 就是接口存在的意义,意图和实现分离。 就好像1+1=2,实现了一个简单加法一样。。。 转载于:https://www.cnblogs.com/l 曾经终败给现在/ 2021年11月27日 06:14/ 0 赞/ 316 阅读
相关 策略模式 策略模式 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。 在策略模式中,我们创建表示各种策略 亦凉/ 2021年09月29日 15:56/ 0 赞/ 298 阅读
相关 策略模式 策略模式(Strategy):定义了一系列算法家族,将每种算法分别封装起来,使得各种算法之间可以互相替换。策略模式可以让算法的变化不影响使用算法的客户,符合开放- 桃扇骨/ 2021年09月22日 23:22/ 0 赞/ 283 阅读
相关 策略模式 13.策略模式 class Program { static void Main(string[] args) 本是古典 何须时尚/ 2021年09月17日 00:00/ 0 赞/ 408 阅读
相关 策略模式 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。 在策略模式中,我们创建表示各种策略的对象和一个行为 忘是亡心i/ 2021年09月16日 23:00/ 0 赞/ 448 阅读
相关 策略模式 策略模式 1. 模式动机 2. 模式定义 3. 模式结构 4. 时序图 5. 代码分析 6. 模式分析 7. 优点 8. 深碍√TFBOYSˉ_/ 2021年08月31日 02:47/ 0 赞/ 548 阅读
相关 策略模式 面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。 策略模式:定义了算法家族,分别封装起来,让它们之间... 灰太狼/ 2020年11月29日 04:23/ 0 赞/ 620 阅读
还没有评论,来说两句吧...