Fun论设计模式之6:策略模式(Strategy Pattern)

  策略模式通常与使用标准模式的Java数据流(stream,Java 8之后有)或者Spark的RDD数据流配合使用,用于改变数据的处理策略,一般用在map和reduce操作。

  意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

  主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

  何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

  如何解决:将这些算法封装成一个一个的类,任意地替换。

  关键代码:实现同一个接口。

  应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。 4、Spark的mapToPair。

  Java中的Map,有两种函数会用到策略模式,比如:computeIfAbsent(不存在则按照策略添加)、computeIfPresent(存在则按照策略更新),需要传入Function类,或者lambda表达式

  内部代码实现是这样的:

 1     @Override
 2     public V computeIfAbsent(final K k, final Function<? super K, ? extends V> function) {
 3         if (function == null) {
 4             throw new NullPointerException();
 5         }
 6         final int hash = hash(k);
 7         int n = 0;
 8         TreeNode<K, V> treeNode = null;
 9         Node<K, V> treeNode2 = null;
10         Node<K, V>[] array;
11         int n2;
12         if (this.size > this.threshold || (array = this.table) == null || (n2 = array.length) == 0) {
13             n2 = (array = this.resize()).length;
14         }
15         final int n3;
16         final Node<K, V> node;
17         if ((node = array[n3 = (n2 - 1 & hash)]) != null) {
18             Label_0169: {
19                 if (node instanceof TreeNode) {
20                     treeNode2 = (treeNode = (TreeNode<K, V>)node).getTreeNode(hash, k);
21                 }
22                 else {
23                     Node<K, V> next = node;
24                     K key;
25                     while (next.hash != hash || ((key = next.key) != k && (k == null || !k.equals(key)))) {
26                         ++n;
27                         if ((next = next.next) == null) {
28                             break Label_0169;
29                         }
30                     }
31                     treeNode2 = next;
32                 }
33             }
34             final V value;
35             if (treeNode2 != null && (value = treeNode2.value) != null) {
36                 this.afterNodeAccess(treeNode2);
37                 return value;
38             }
39         }
40         final V apply = (V)function.apply(k);
41         if (apply == null) {
42             return null;
43         }
44         if (treeNode2 != null) {
45             treeNode2.value = apply;
46             this.afterNodeAccess(treeNode2);
47             return apply;
48         }
49         if (treeNode != null) {
50             treeNode.putTreeVal(this, array, hash, k, apply);
51         }
52         else {
53             array[n3] = this.newNode(hash, k, apply, node);
54             if (n >= 7) {
55                 this.treeifyBin(array, hash);
56             }
57         }
58         ++this.modCount;
59         ++this.size;
60         this.afterNodeInsertion(true);
61         return apply;
62     }
63
64     @Override
65     public V computeIfPresent(final K k, final BiFunction<? super K, ? super V, ? extends V> biFunction) {
66         if (biFunction == null) {
67             throw new NullPointerException();
68         }
69         final int hash = hash(k);
70         final Node<K, V> node;
71         final V value;
72         if ((node = this.getNode(hash, k)) != null && (value = node.value) != null) {
73             final V apply = (V)biFunction.apply(k, value);
74             if (apply != null) {
75                 node.value = apply;
76                 this.afterNodeAccess(node);
77                 return apply;
78             }
79             this.removeNode(hash, k, null, false, true);
80         }
81         return null;
82     }

HashMap中用策略模式的函数

  可以看到,传入的function对象在某些执行路线下,会被执行apply()以使用里面的策略。

  外部可以这样调用:

  myMap.computeIfAbsent(keyC, k -> k + "2");//如果keyC没有对应值,则把值设为keyC和"2"这个字符串的连接

  myMap.computeIfPresent(keyC, (v1, v2) -> v1 + "," + v2);//如果keyC有对应值,则把值设为原值和逗号和插入值这个字符串的连接

  这样,Map就无需为这些策略继承过多的子类,减少了无效的开发量。

  如果需要用默认function,其实Java内部也有一些内部实现。

  优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

  缺点: 1、策略类会增多。(用语法糖,比如lambda就可以解决) 2、所有策略类都需要对外暴露。(这个其实问题不大,控制一下开发流程和查看权限就可以了)

  使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

  注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

原文地址:https://www.cnblogs.com/dgutfly/p/11621778.html

时间: 2024-10-14 04:23:02

Fun论设计模式之6:策略模式(Strategy Pattern)的相关文章

设计模式之一:策略模式(Strategy Pattern)

在介绍策略模式之前先说下两个设计原则: 1.  Identify the aspects of your application that vary and separate them from what  stays the same.找到系统中变化的部分,将变化的部分同其它稳定的部分隔开. 2.  Program to an interface, not an implementation.面向接口编程,而不要面向实现编程. 那什么是策略模式呢? The Strategy Pattern d

设计模式 - 策略模式(Strategy Pattern) 具体解释

策略模式(Strategy Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26577879 本文版权全部, 禁止转载, 如有须要, 请站内联系. 策略模式: 定义了算法族, 分别封装起来, 让它们之间能够相互替换, 此模式让算法的变化独立于使用算法的客户. 对于父类的子类族须要常常扩展新的功能, 为了使用父类比較灵活的加入子类, 把父类的行为写成接口(interface)的形式; 使用set()方法

设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕该功能.如查找.排序等,一种经常使用的方法是硬编码(Hard Coding)在一个类中,如须要提供多种查找算法,能够将这些算法写到一个类中,在该类中提供多个方法,每个方法相应一个详细的查找算法:当然也能够将这些查找算法封装在一个统一的方法中,通过if-else-或者case等条件推断语句来进行选择.

设计模式 - 策略模式(Strategy Pattern) 详解

策略模式(Strategy Pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26577879 本文版权所有, 禁止转载, 如有需要, 请站内联系. 策略模式: 定义了算法族, 分别封装起来, 让它们之间可以相互替换, 此模式让算法的变化独立于使用算法的客户. 对于父类的子类族需要经常扩展新的功能, 为了使用父类比较灵活的添加子类, 把父类的行为写成接口(interface)的形式; 使用set()方法,

设计模式实现C++ --策略模式Strategy(对象行为型)

1.问题 出行旅游:我们可以有几个策略可以考虑:可以骑自行车,汽车,做火车,飞机.每个策略都可以得到相同的结果,但是它们使用了不同的资源.选择策略的依据 是费用,时间,使用工具还有每种方式的方便程度. 2.解决方案 策略模式:定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换.本模式使得算法可独立于使用它的客户而变化. 策略模式把对象本身和运算规则区分开来,其功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性的思想. strategy模式类图: 3.应用场景 1. 

如何让孩子爱上设计模式 ——14.策略模式(Strategy Pattern)

如何让孩子爱上设计模式 --14.策略模式(Strategy Pattern) 描述性文字 本节讲解的是行为型设计模式中的第一个模式: 策略模式, 这个模式非常简单,也很好理解. 定义一系列的算法,把每个算法封装起来,并使得他们可以相互替换, 让算法独立于使用它的客户而变化. 一般用来替换if-else,个人感觉是面向过程与面向对象思想的 过渡,这里举个简易计算器的栗子,帮助理解~ 普通的if-else/switch计算器 普通的面向过程if-else简易计算器代码如下: 运行结果如下: 这里我

【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查找.排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法:当然也可以将这些查找算法封装在一个统一的方法中,通过if-else-或者case等条件判断语句来进行选择.这

二十四种设计模式:策略模式(Strategy Pattern)

策略模式(Strategy Pattern) 介绍定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例有一个Message实体类,对它的操作有Insert()和Get()方法,持久化数据在SqlServer数据库中或Xml文件里(两种可互换的算法).由客户端决定使用哪种算法. MessageModel using System; using System.Collections.Generic; using System.Text; na

策略模式(Strategy Pattern)

策略模式(Strategy Pattern) 抛开晦涩的定义,首先看一个例子: 我们想要创建一个模拟鸭子的游戏,在这个游戏中,会有各种类型的鸭子,比如mallard duck,red head duck,rubber duck(除了rubber duck(橡皮鸭),看见这其余两种鸭子很好奇,于是查找相关图片,发现mallard duck是绿头鸭,red head duck是红头鸭,自己生活中还没有见过,有趣,哈哈!三种鸭子图片如下所示). 回归话题,在这个模拟鸭子的游戏中,各种鸭子均有两种能力,

设计模式(行为型)之策略模式(Strategy Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之迭代器模式(Iterator Pattern)>http://blog.csdn.net/yanbober/article/details/45497881 概述 使用策略模式可以定义一些独立的类来封装不同的算法,每一个类封装一种具体的算法,在这里,每一个封