前言
本文是对《Adroid 源码设计模式解析与实战》 何红辉、关爱民 著 人民邮电出版社所做的读书笔记。文章是对本书的一些列学习笔记,如若有侵犯到作者权益,还望作者能联系我,我会及时下架。
这本书不错,有兴趣的同学可以买原书看看。
感兴趣的朋友欢迎加入学习小组QQ群: 193765960。
版权归作者所有,如有转发,请注明文章出处:https://xiaodanchen.github.io/archives/
1. 策略模式的定义
假如在开发中遇到下列情况:
- 针对同一问题有多重处理方式,他们仅仅是具体行为有差别。
- 需要安全的封装多种同一类型的操作。
- 同一个抽象类有多个子类,而子类的使用又是互斥的。
遇到上述几种情况时,我们可以使用策略模式。策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
2. 策略模式的实现
通常如果一个问题有多个解决方案时,最简单的方法就是利用if-else或者switch语句方式根据不同的情景选择不同的解决方案,但这种简单的方案问题太多,例如耦合性太高、代码臃肿、难于维护等。而且违反开闭原则,而应对这种情况策略模式是很好的选择。
举个栗子:假如我们要设计一个出行交通工具(公交车、地铁)计费模块。
2.1 屌丝程序猿小明
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| * 价格计算器类 */ public class PriceCalculator{ private static final int BUS = 1; private static final int SUBWAY = 2; public static void main(String[] args){ PriceCalculator calculator = new PriceCalculator(); System.out.println("坐16公里的公交车票价为:"+calculator.calculatePrice(16,BUS)); System.out.println("坐16公里的地铁票价为:"+calculator.calculatePrice(16,SUBWAY)); } * 公交车,十公里之内1元,超过十公里后没加一元钱可以乘车公里。 */ private int busPrice(int km){ int extraTotal = km-10; int extraFactor = extraTotal/5; int fraction = extraTotal%5; int price = 1+extraFactor*1; return fraction>0?++price:price; } * 地铁,6公里(含)之内3元,6~12公里(含)4元, * 12~22公里(含)5元,22~32公里(含)6元,。 */ private int subwayPrice(int km){ if(km<=6){ return 3; }else if(km>6 && km<=12){ return 4; }else if(km>12 && km<=22){ return 5; }else if(km>22 && km<=32){ return 6; } return 7; } int calculatePrice(int km,int type){ if(type == BUS){ return busPrice(km); }else if(type == SUBWAY){ return subwayPrice(km); } return 0; } }
|
解析
首先,PriceCalculator类很明显的问题就是违反了单一职责原则,他承担了计算公交车和地铁乘车价格的职责。
其次,PriceCalculator类违反了开闭原则,通过if-else语句的形式来判断使用哪种计算方式,当我们增加一种出行方式时比如出租车,我们就需要在PriceCalculator类中增加一个方法来计算出租车出行的价格,并且需要在calculatePrice方法中增加新的条件分支。
这样随着业务的复杂,这个代码会越来越臃肿,难以维护。
2.2 装逼程序猿小民
小民采用策略模式来设计该功能
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| * 计价策略接口 */ public interface CalculateStrategy{ * 按距离计算价格 * @param km 距离 * @return 价格 */ int calculatePrice(int km); } * 公交车计价策略 */ public class BusStrategy implements CalculateStrategy{ * 公交车,十公里之内1元,超过十公里后没加一元钱可以乘车公里。 */ @Override public int calculatePrice(int km){ int extraTotal = km-10; int extraFactor = extraTotal/5; int fraction = extraTotal%5; int price = 1+extraFactor*1; return fraction>0?++price:price; } } * 地铁计价策略 */ public class BusStrategy implements CalculateStrategy{ * 地铁,6公里(含)之内3元,6~12公里(含)4元, * 12~22公里(含)5元,22~32公里(含)6元,。 */ @Override public int calculatePrice(int km){ if(km<=6){ return 3; }else if(km>6 && km<=12){ return 4; }else if(km>12 && km<=22){ return 5; }else if(km>22 && km<=32){ return 6; } return 7; } } * 价格计算器类 */ public class PriceCalculator{ CalculateStrategy mStrategy; public static void main(String[] args){ PriceCalculator calculator = new PriceCalculator(); calculator.setStrategy(new BusStrategy()); System.out.println("坐16公里的公交车票价为:"+calculatePrice(16)); } public void setStrategy(CalculateStrategy strategy;){ mStrategy = strategy } public int calculatePrice(int km){ if(null == mStrategy){ return 0; } return mStrategy.calculatePrice(km); } }
|
解析
经过上面的重构之后,去掉了各种各样的if-else语句,结构变得更加清晰。
不同的策略封装符合单一职责原则。
PriceCalculator的实际调用符合开闭原则和依赖注入原则,便于扩展。
3. 总结
策略模式主要用来分离算法,在相同的行为抽象下有不同的具体实现策略。这个模式很好的演示了开闭原则,也就是定义抽象,注入不同的实现,从而达到很好的可扩展性。