Java设计模式6:策略模式
策略模式
策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
策略模式的结构
策略模式是对算法的包装,是把使用算法的责任和算法本身分开。策略模式通常是把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。
策略模式涉及到三个角色:
1、环境角色
持有一个策略Strategy的引用
2、抽象策略角色
这是一个抽象角色,通常由一个接口或抽象类实现,此角色给出所有具体策略类所需的接口
3、具体策略角色
包装了相关算法或行为
策略模式示例
有一个抽象的策略接口:
public interface Strategy {public void useStrategy(); }
实现两种具体的策略:
public class StrategyA implements Strategy {public void useStrategy(){System.out.println("StrategyA.useStrategy()");} }
public class StrategyB implements Strategy {public void useStrategy(){System.out.println("StrategyB.useStrategy()");} }
某个类持有策略的引用:
public class Context {private Strategy strategy;public Context(Strategy strategy){this.strategy = strategy;}public void strategyMethod(){strategy.useStrategy();} }
调用这个类的地方可以自行决定使用哪种策略:
public class TestMain {public static void main(String[] args){Strategy strategyA = new StrategyA();Strategy strategyB = new StrategyB();Context context = new Context(strategyA);context.strategyMethod();context = new Context(strategyB);context.strategyMethod();} }
策略模式的使用场景
1、购物系统
举一个实际例子吧。假如有一个购物系统,在用户付款的时候,会产生很多场景,根据用户的不同情况算出不同用户要付款的金额,这时候最直观的一种做法是:
在付款的里面写N多的if...else if...else,判断用户的场景,根据场景计算用户付款金额。
这种设计明显违反了开闭原则。开闭原则的"闭",指的是对修改关闭,但是这里假如算法又多了几种,那么必须再次修改这个付款的类。
这时候就可以使用策略模式。在付款的类里面持有一个付款接口的引用,每次根据不同场景传入一个具体的策略就好了。比如A类中要使用S0算法,就传入一个S0策略;B类中要使用S1算法,就传入一个S1算法。不需要把判断都放在付款的类中,代码的可读性、可维护性也更高了。付款这个类甚至可以直接生成一个.class文件放在一个jar包里面供调用。
2、使得代码更优雅、更易维护
假如你的代码中某处有一个打分系统,你为这个打分系统写了一段非常长的逻辑,某天,产品部门的同事找你,给我换一段打分逻辑,此时,有两种做法:
(1)把原有的打分逻辑删除,但这么做一个缺点是是看不到以前的打分算法了,另一个缺点是如果以后打分算法要换回来就找不到代码,虽然SVN和GIT这种版本管理工具都有历史提交记录的功能,但还是显得麻烦
(2)把原有的打分逻辑注释,但这么做的最大缺点是代码中有大量的注释,尤其在策略逻辑非常长的时候,这就导致了代码的可读性非常差
此时,就可以使用策略模式,将打分逻辑抽象为一种策略,换打分策略,新增一个策略的实现类,最后再让代码中传入新的策略实现类即可。
策略模式在Java中的应用及解读
策略模式在Java中的应用,这个太明显了,因为Comparator这个接口简直就是为策略模式而生的。Comparable和Comparator的区别一文中,详细讲了Comparator的使用。比方说Collections里面有一个sort方法,因为集合里面的元素有可能是复合对象,复合对象并不像基本数据类型,可以根据大小排序,复合对象怎么排序呢?基于这个问题考虑,Java要求如果定义的复合对象要有排序的功能,就自行实现Comparable接口或Comparator接口,看一下sort带Comparator的重载方法:
1 public static <T> void sort(List<T> list, Comparator<? super T> c) { 2 Object[] a = list.toArray(); 3 Arrays.sort(a, (Comparator)c); 4 ListIterator i = list.listIterator(); 5 for (int j=0; j<a.length; j++) { 6 i.next(); 7 i.set(a[j]); 8 } 9 }
跟一下第3行:
1 public static <T> void sort(T[] a, Comparator<? super T> c) { 2 T[] aux = (T[])a.clone(); 3 if (c==null) 4 mergeSort(aux, a, 0, a.length, 0); 5 else 6 mergeSort(aux, a, 0, a.length, 0, c); 7 }
传入的c不为null,跟一下第6行的mergeSort:
1 private static void mergeSort(Object[] src, 2 Object[] dest, 3 int low, int high, int off, 4 Comparator c) { 5 int length = high - low; 6 7 // Insertion sort on smallest arrays 8 if (length < INSERTIONSORT_THRESHOLD) { 9 for (int i=low; i<high; i++) 10 for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--) 11 swap(dest, j, j-1); 12 return; 13 } 14 15 // Recursively sort halves of dest into src 16 int destLow = low; 17 int destHigh = high; 18 low += off; 19 high += off; 20 int mid = (low + high) >>> 1; 21 mergeSort(dest, src, low, mid, -off, c); 22 mergeSort(dest, src, mid, high, -off, c); 23 24 // If list is already sorted, just copy from src to dest. This is an 25 // optimization that results in faster sorts for nearly ordered lists. 26 if (c.compare(src[mid-1], src[mid]) <= 0) { 27 System.arraycopy(src, low, dest, destLow, length); 28 return; 29 } 30 31 // Merge sorted halves (now in src) into dest 32 for(int i = destLow, p = low, q = mid; i < destHigh; i++) { 33 if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0) 34 dest[i] = src[p++]; 35 else 36 dest[i] = src[q++]; 37 } 38 }
第10行,根据Comparator接口实现类的compare方法的返回结果决定是否要swap(交换)。
这就是策略模式,我们可以给Collections的sort方法传入不同的Comparator的实现类作为不同的比较策略。不同的比较策略,对同一个集合,可能会产生不同的排序结果。
认识策略模式
应当明白,策略模式的重心不是如何实现算法(就如同工厂模式的重心不是工厂中如何产生具体子类一样),而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。
策略模式有一个很大的特点就是各策略算法的平等性。对于一系列具体的策略算法,大家的地位是完全一样的,正因为这个平等性,各个算法之间才可以相互替换。
运行期间,每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略中实现切换。
策略模式的优缺点
优点
1、避免了多重条件if...else if...else语句,多重条件语句并不容易维护
2、策略模式提供了管理相关算法簇的办法,恰当使用继承可以把公共代码移到父类,从而避免了代码重复
缺点
1、客户端必须知道所有的策略类,并自行决定使用 哪一个策略,这意味着客户端必须理解这些算法的区别,以便选择恰当的算法
2、如果备选策略很多,对象的数据会很多
Java设计模式6:策略模式相关推荐
- Java设计模式之策略模式与状态模式
一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. 好了,定义看看就完了,我知道你很烦看定义. 二.策 ...
- Java设计模式之策略模式(UML类图分析+代码详解)
大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...
- Java设计模式之策略模式+工厂模式+模板模式
Java设计模式之策略模式+工厂模式+模板模式 1.策略模式+工厂模式+模板模式 个人的理解:实际开发工程中,一些业务很复杂的逻辑使用很多的 if 或者 if···else 语句,不利于维护和扩展,为 ...
- 【Java设计模式】策略模式
(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景知识 策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法.比如每 ...
- Java 设计模式之策略模式
一.了解策略模式 1.1 什么是策略模式 策略模式 (Strategy Pattern) 是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换.此模式让算法的变化独立于使用算法的客 ...
- java解决策略膨胀_折腾Java设计模式之策略模式
简介 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式.简单理解就是一组算法,可以互换,再简单点策略就是封装算法. 意图 定义一 ...
- 【设计模式】java设计模式之 -- 策略模式
对于代码中总是会有需要变化的部分和需要固定不变的部分.对于需要变化的部分,一般可以采用继承的方式,让子类对父类的方法进行重写,以改变已有的行为:如果变化的部分并不是所有子类都必须要有的,那就可以采用接 ...
- Java设计模式之策略模式---写的比较有趣,推荐大家看看
原文:http://blog.csdn.net/jason0539/article/details/45007553 背景 在软件开发中常常遇到这种情况,实现某一个功能有多种算法或者策略,我们可以根据 ...
- 《Java设计模式之策略模式》
<二 >策略模式 相信很多人都玩过魔兽世界这款游戏,它里面的战士有三种姿态:防御.狂暴.战斗,那么在不同的场景下我们需要使用不通的姿态,比如当MT抗怪就需要使用防御姿态,战场需要使用战 ...
- Java设计模式之——策略模式
策略模式的简单介绍 在软件开发中常常遇到这样的情况:实现某一个功能可以有多种算法或者策略,我们根据事件情况选择不同的算法或者策略来完成该功能.例如,排序算法,可以使用插入排序.归并排序.冒泡排序等. ...
最新文章
- android地图获取坐标位置,android 百度地图 根据得到的经纬度 获取位置信息
- 最重要的事情只有一件
- 【Bash百宝箱】shell内建命令之echo、printf
- C++STL的vector中front(),back(),begin(),end()的用法
- androidStudio快捷键概览
- 编译Windows版本ffmpeg:cygwin方式通过
- H3C基础配置命令(一)
- oracle 按汉字拼音顺序排序
- Java-Web总结03
- iphone 3.1.2开发环境搭建——linux平台
- 移动运营商ipcc文件_如何在苹果官网提取IPCC文件?
- iOS开发:The app icon set named AppIcon did not have any applicable content
- 求两个集合的交集和并集
- gffread 常用使用自己速记
- 使用gparted工具扩充vmware UBUNTU虚拟机磁盘空间
- windows 8.1 下91手机助手解决方案
- 高通平台GPS工程测试接收参数解析
- golang iris mysql_golang iris使用
- APP应用市场数据分析
- 自制html5塔防游戏