对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
先看个故事便于理解策略模式
话说当年东吴孙权为刘备借走了荆州不还而耿耿于怀,却不料甘夫人去世,周郎顿时计上心来,让孙权将其妹嫁与刘备,骗刘备来东吴完婚。刘备又不是傻子,当然知道其中的猫腻,当即表态:打死也不去。诸葛亮却说无妨,当下给了赵云三个锦囊妙计,让他陪刘备去东吴完婚……最后的结果大家都知道,赵云在恰当的时候一一打开三个锦囊妙计,从而将危机一一化解。周瑜只落了个“周郎妙计安天下,赔了夫人又折兵”的笑柄。
这个故事,我们感兴趣的是三个锦囊妙计。诸葛亮一定是运用策略模式的高手,我们想啊:诸葛亮为什么要这么麻烦,做三个锦囊,他完全可以只做一个锦囊,将这三个妙计都写在它上面。可他没有这么做,而是正确的运用了策略模式做了三个锦囊。这样做的好处十分明显:诸葛亮一个锦囊写一个妙计,他的思路十分清晰,不会三个计策相互混乱。而赵云看妙计的时候也十分方便,什么时候看哪个妙计,使用十分方便,如果三个妙计混在一起,他就没这么方便了。
现在看来,这个故事正包含了策略模式的解决问题的思路:解决某一问题有多种方法或算法,如诸葛亮给了三个妙计,类的提供者要将这多种方法或算法独立开来,如诸葛亮将三个妙计分三个锦囊装,类的使用者,如赵云,在相应的条件,如故事中的恰当时间,使用相应的方法或算法。
比较器相当于锦囊,里面可以装许多妙计,它的实现类相当于妙计。
**
public class Sorter<T> {
public void sort(T[] arr, Comparator<T> comparator) {
for(int i=0; i<arr.length - 1; i++) {
int minPos = i;
for(int j=i+1; j<arr.length; j++) {
minPos = comparator.compare(arr[j],arr[minPos])==-1 ? j : minPos;
}
swap(arr, i, minPos);
}
}
//sort(int)
void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
public class CatHeightComparator implements Comparator<Cat> {
@Override
public int compare(Cat o1, Cat o2) {
if(o1.height > o2.height) return -1;
else if (o1.height < o2.height) return 1;
else return 0;
}
}
public class CatWeightComparator implements Comparator<Cat> {
@Override
public int compare(Cat o1, Cat o2) {
if(o1.weight < o2.weight) return -1;
else if (o1.weight > o2.weight) return 1;
else return 0;
}
}
public class DogComparator implements Comparator<Dog> {
@Override
public int compare(Dog o1, Dog o2) {
if(o1.food < o2.food) return -1;
else if (o1.food > o2.food) return 1;
else return 0;
}
}