1. 杂言:
好久没更新博客了,个人毅力问题。其实回想起来,如果那时就完成了24种设计模式的学习。这时候应该算是复习了。而且对设计模式的了解应该更上一层楼才对。所以逝者如斯夫,不舍昼夜。年轻人应该好好珍惜时光。话说,对于设计模式,很多人讲这种东西懂几个基础就好了,可能以后还用不上。其实这个问题,就好像我在大学学自动化时,问老师,我们这种学单片机的,干嘛学网络技术这种以后可能用不上的东西?老师说,学的东西总是潜默移化的影响着你。确实,像我这种爱好画画,平时偶尔看看文科类的书,大学学自动化,出来做IT行业的人来说。学东西,应当犹如韩信点兵,多多益善。
2. 理论:
它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法的变化不会影响到使用算法的客户。(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.)
3. UML图:
原图
我画的类图
4. 举例:
在写这篇文章前百度过一些别 人的例子,好像大多喜欢举一些鸡鸭猪狗之类的例子来说明。感觉这样很容易误导人,以为策略模式是创建型模式。其实策略模式是行为型模式。它关注的是对象的行为,而不是对象的创建。
a. 遇到问题
一天,一个博士发明了一台机器,能通过输入两个人的名字进行计算得出谁更帅,谁人品更好,谁更长寿。这台机器很快引起了村子的轰动。人们纷纷跑过来玩。一次5毛,博士很快成为了村子的高富帅。完毕。下面我们来瞧瞧这台神秘机器怎么实现的。
b.代码实现
首先实现接口,定义统一方法。
package prov.sue.design.strategy;
public interface IStrategy {
public void compare(String name1,String name2);
}
然后便是谁更帅的实现算法
package prov.sue.design.strategy;
public class HandsomeStrategy implements IStrategy {
@Override
public void compare(String name1, String name2) {
// TODO Auto-generated method stub
System.out.println(name1+"更帅");
}
}
谁人品更好算法
package prov.sue.design.strategy;
public class LuckStrategy implements IStrategy {
@Override
public void compare(String name1, String name2) {
// TODO Auto-generated method stub
System.out.println(name1+"人品更好");
}
}
谁更长寿算法
package prov.sue.design.strategy;
public class LongevityStrategy implements IStrategy{
@Override
public void compare(String name1, String name2) {
// TODO Auto-generated method stub
System.out.println(name1+"更长寿");
}
}
环境角色,也就是这台机器了
package prov.sue.design.strategy;
public class CompareContext {
private IStrategy iStrategy;
public void compareHandsome(String name1,String name2)
{
iStrategy=new HandsomeStrategy();
iStrategy.compare(name1, name2);
}
public void compareLuck(String name1,String name2)
{
iStrategy=new LuckStrategy();
iStrategy.compare(name1, name2);
}
public void compareLongevity(String name1,String name2)
{
iStrategy=new LongevityStrategy();
iStrategy.compare(name1, name2);
}
}
最后,看看怎么使用这个机器。
package prov.sue.design;
import prov.sue.design.strategy.CompareContext;
public class DesignMain {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
CompareContext context=new CompareContext();
context.compareHandsome("小明", "小东");
context.compareLuck("小明", "小东");
context.compareLongevity("小明", "小东");
}
}
小明和小东大战3回合,终于得出了结论
小明更帅
小明人品更好
小明更长寿
好吧,小东别哭,可能小明女朋友没你多。
5. 应用实例:
在Java的集合框架中,构造Map或者Set时传入Comparator比较器,或者创建比较器传入Collections类的静态方法中作为方法的参数为Collection排序时,都使用到了策略模式。
LinkedList<String> list = new LinkedList<String>(); list.add("arthinking"); list.add("Jason"); list.add("X"); //创建一个逆序的比较器 Comparator<String> r = Collections.reverseOrder(); //通过逆序的比较器进行排序 Collections.sort(list,r);
使用Collections.reverseOrder()方法床架一个比较器之后,再调用Collections.sort(list, r)把比较器传入该方法中进行排序,下面就看一下sort(list, r)中的代码:
public static <T> void sort(List<T> list, Comparator<? super T> c) { Object[] a = list.toArray(); Arrays.sort(a, (Comparator)c); ListIterator i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set(a[j]); } }
Arrays.sort(a, (Comparator)c);这句继续把比较器传入处理,下面是Arrays.sort(a, (Comparator)c)的具体操作:
public static <T> void sort(T[] a, Comparator<? super T> c) { T[] aux = (T[])a.clone(); if (c==null) mergeSort(aux, a, 0, a.length, 0); else mergeSort(aux, a, 0, a.length, 0, c); }
这里又调用了mergeSort(aux, a, 0, a.length, 0, c);继续传递比较器,再跟进去,发现如下执行代码:
private static void mergeSort(Object[] src, Object[] dest, int low, int high, int off, Comparator c) { int length = high - low; // Insertion sort on smallest arrays if (length < INSERTIONSORT_THRESHOLD) { for (int i=low; i<high; i++) for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--) swap(dest, j, j-1); return; } // Recursively sort halves of dest into src int destLow = low; int destHigh = high; low += off; high += off; int mid = (low + high) >>> 1; mergeSort(dest, src, low, mid, -off, c); mergeSort(dest, src, mid, high, -off, c); // If list is already sorted, just copy from src to dest. This is an // optimization that results in faster sorts for nearly ordered lists. if (c.compare(src[mid-1], src[mid]) <= 0) { System.arraycopy(src, low, dest, destLow, length); return; } // Merge sorted halves (now in src) into dest for(int i = destLow, p = low, q = mid; i < destHigh; i++) { if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0) dest[i] = src[p++]; else dest[i] = src[q++]; } }
这段代码有点复杂,我们跳出其中使用到比较器的代码分析:
c.compare(dest[j-1], dest[j])>0;
这里的compare方法在Comparator接口中也有定义:
public interface Comparator<T> { int compare(T o1, T o2); }
由于这里使用泛型实现了Comparator,所以实际执行时,会根据比较器的具体实现类调用到实现代码,也就是上面创建的逆序比较器的compare方法,其实现如下:
public int compare(Comparable<Object> c1, Comparable<Object> c2) { return c2.compareTo(c1); }
抽象策略角色类为:Comparator接口
真实策略角色类为:ReverseComparator
我们在这里传入不同的比较器就会得到不同的排序的执行方法了:
Collections.sort(list,r);
本文链接: http://www.itzhai.com/java-source-code-analysis-strategy-pattern-implementation-in-java-collections-framework-embodied-in-the-code.html
6. 探讨 无