Java 数组的工具类 Arrays 中的排序方法是典型的应用了策略模式的例示。其定义如下:
public static <T> void sort(T[] a, Comparator<? super T> c){
//...
}
意义是,按照给定的策略执行(Comparator)对数组进行排序。sort 方法是要做的事情,T[] a 这个数组是策略作用的对象,Comparator策略本身。其中 Comparator 是一个泛型接口,所有实现了策略接口的具体策略都可以作为参数传入。Comparator 使用通配符,允许利用 T 的超类的策略对 T 进行操作。例如我们有一个书类如下。
public class Book {
private double price;
public Book(double price){
this.price = price;
}
public double getPrice() {
return price;
}
}
我们利用 sort 算法为其排序时,可以自行选择排序的依据,即策略。
public class StrategyTest {
@Test
public void test() {
Book[] books = new Book[]{new Book(10.00), new Book(8.70), new Book(12.35), new Book(35.50), new Book(12.35)
};
//排序策略 1: 按照书的价格升序排列
Arrays.sort(books, new Comparator<Book>(){
@Override
public int compare(Book o1, Book o2) {
return Double.compare(o1.getPrice(), o2.getPrice());
}
});
System.out.println("排序策略 1: 按照书的价格升序排列");
for(Book book : books){
System.out.print(book.getPrice() + "\t");
}
//排序策略 2: 按照书的价格降序排列
Arrays.sort(books, new Comparator<Book>(){
@Override
public int compare(Book o1, Book o2) {
return Double.compare(o2.getPrice(), o1.getPrice());
}
});
System.out.println("排序策略 2: 按照书的价格降序排列");
for(Book book : books){
System.out.print(book.getPrice() + "\t");
}
}
}
这里采用了匿名内部类来提供策略,实际应用当中,策略也常常作为既定的处理方式提供给用户选择。例如 String 类中提供了大小写不敏感的排序策略。
public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
private static class CaseInsensitiveComparator
implements Comparator<String>, java.io.Serializable {
public int compare(String s1, String s2) {
int n1 = s1.length();
int n2 = s2.length();
int min = Math.min(n1, n2);
for (int i = 0; i < min; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 != c2) {
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2) {
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2) {
// No overflow because of numeric promotion
return c1 - c2;
}
}
}
}
return n1 - n2;
}
/** Replaces the de-serialized object. */
private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
}
Java 集合的工具类 Collections 也提供了类似的 sort 方法。一般地,需要排序的类也会通过实现 Comparable 接口提供一种默认的自然排序方法,而当自然排序不能满足需求时,才需要使用 Comparator 策略。另外 Collections 也提供了一个逆自然排序方法的策略。对于实现了 Comparable 接口的类,在对其进行排序时,可以使用 Collections 提供的逆序排序策略。
// 按照 arrayOfComparable (实现了 Comparable 接口) 自然排序
Arrays.sort(arrayOfComparable);
// 按照 arrayOfComparable 自然排序算法逆序排序
Arrays.sort(arrayOfComparable, Collections.reverseOrder());