设计模式的某一个模式,是用来解决某一种特定情况下,简单的逻辑会导致代码复杂甚至冗余。如果程序的某个方法,存在有好几种并行的处理手段。那么我们最好是采用if...else if...或switch...case... 但,如果这些处理手段复杂度高,使用范围不小----通常是算法。采用策略模式方法,会在灵活性,耦合度,代码维护难度,算法保护等方面具有优势。
策略模式是用方法的重写带替代不同名字的方法,利用面向对象的特征,使增加或减小可选择的算法时,直接传入不同的子类来进行算法选择。
先看看if...else if... 和 switch...case...
if...else if... 优势:可以进行不同类型的判断来选择进行哪种操作。
switch...case... 优势:使用单一的判断要素,快速选择到进行哪种操作
在if...else if... 和 switch...case...的情况下:
如果每一个操作都很复杂,那么我们应该选择使用一个方法来包括起来。即,每个case的选择下面有一个方法。
如果需要进行的选择偏多,那就会有很多个对应的方法,来完成这功能,而且每个方法的名字不一样,而且每个方法完成的功能差不多。
如果这个方法,不仅仅在这一个类里面使用,那这些被复用的方法,就需要些很多类里面都使用if...else if... 或 switch...case... 来判断。
然后我们可以想象一下,基于java的伪代码是这个样子的
getItem( int itemMunber ){
Switch(itemMunber)
Case 0:
Items.findItemZore();
Case1:
Items.findItemOne();
Case2:
Items.findItemTwo();
}
这里我们会面临几个不满意的地方,
1:怎么样直观的体现出itemNumber?
可以考虑使用特征参数来代替itemMunber,而且由于会有不只一个类来调用这个getItem方法,所以,需要专门创建一个静态类或者接口来提供itemMunber的文字描述。
2:怎么样来命名这个方法名?
可以考虑认真区分几个getItem的区别来命名,或许是返回值,或者是作用目标等。
在调用时,其伪代码是这样的
GET_ITEM_ZORE = 0;
getItem(GET_ITEM_ZORE );
虽然外面给出了解决方案,但是,如果我们继续夸大条件,需要选择的类型更多,每个方法算法更复杂,调用这个getItem方法的类更多。那么上面的两个问题就会凸显出来,解决起来也更加繁杂。
下面,我们在用策略模式来走一遍,从中感受到策略模式的灵活性,耦合度,代码维护难度,算法保护的优势。
策略模式是充分利用面向对象的特征,继承与多态。getItem的传入不再是数,而是类。
这个方法的伪代码变成:
getItem( Items items ){
items.findItem();
}
在调用是这样的
getItem(ZoreItem);
这个ZoreItem是继承至Items方法。而重写了findItem方法。类容和上文的Items.findItemZore()是一样的。
可以看到,这个模式的本质就是进行方法选择的时候,由提供特征参数来进行选择,变成提供特定子类来进行操作。
其最明显的优势是:减少了if...else if...的反复判断。
以及我之前提到的极大优势:
灵活性:提供的子类,每个程序员均可以增加,我们想新增一个方法,就新增一个Items 的子类。而对比if...else if方法,则需要增加一个else if以及其判断用的特征参数。甚至需要增加每个地方的此参数。
耦合度:是策略模式的最大优势。新增一个方法,不只需增加一个新类即可。不需要在原生类中去增加一个方法。也不需要,去增加else if。对现有程序的改动特别小。
代码维护难度:在进行维护的时候,只需要对针对的有问题的类进行修改。如果要去掉某个类,就直接将该类以及调用该类的地方去掉即可,不需要去整理特征参数。
算法保护:父类,以及已经创建好的类,直接使用无需修改。更加可以做成包,供人使用,而对方可以直接使用现成的,也可以自己继承来做。
策略模式的案例:
Android的Collection的Sort方法就是一个经典的策略模式
Collection.Sort(LIst,Comparator);
后面这个java.util.Comparator就是一个interface是希望我们自己去实现的算法。
而实现这个算法的自定义的类,就放在这个方法里面,用来对List排序。
以上,就是关于策略模式的学习。
主要关于其使用场景用到if...else if... 但用起来又不顺畅的地方,以及该模式的优势:灵活,解耦等。