}
}
复制代码
这个排序工具类有一个问题,就是仅支持int数组,如果需要被处理的是Object对象等类型就不行了,所以让我们来一步一步用策略模式来改造一下。
首先新建两个用于测试的类Cat和Dog:
package com.cc.strategy;
public class Cat {
int weight, height;
public Cat(int weight, int height) {
this.weight = weight;
this.height = height;
}
@Override
public String toString() {
return “Cat{” +
“weight=” + weight +
“, height=” + height +
‘}’;
}
}
复制代码
package com.cc.strategy;
public class Dog {
int food;
public Dog(int food) {
this.food = food;
}
@Override
public String toString() {
return “Dog{” +
“food=” + food +
‘}’;
}
}
复制代码
其中Cat有两个属性,重量weight和高度height,Dog有一个饭量food。
首先我们希望Sorter类可以做到,将Cat数组根据weight排序,那么我们可以这样写:
新建一个比较的实现类Comparable(我知道Java已经有这个实现类了,但是为了加深理解,让我们手撸一个吧):
package com.cc.strategy;
public interface Comparable {
int compareTo(T o);
}
复制代码
其中泛型T可能会有疑惑,后面会提到,
为了支持Sorter排序,Cat需要实现这个Comparable类,修改后如下:
package com.cc.strategy2;
// 上面提到的泛型可以在此处指定…
public class Cat implements Comparable {
int weight, height;
public Cat(int weight, int height) {
this.weight = weight;
this.height = height;
}
/**
-
…然后本来是T o格式,使用了泛型并且在类上指定之后可以在实现函数中直接用Cat c的方式指定
-
这样其实是自动做了一层转换:Object o => Cat c
-
如果不用泛型,就要这样多写一行:
-
Cat c = (Cat)o;
*/
@Override
public int compareTo(Cat c) {
if (this.weight < c.weight) {
return -1;
} else if (this.weight > c.weight) {
return 1;
} else {
return 0;
}
}
@Override
public String toString() {
return “Cat{” +
“weight=” + weight +
“, height=” + height +
‘}’;
}
}
复制代码
Sorter排序类也要修改,从原来只接受int[]变成Comparable[],即所有实现了Comparable的对象:
package com.cc.strategy2;
public class Sorter {
public void sort(Comparable[] arr) {
for (int i = 0; i < arr.length; i++) {
int minPos = i;
for (int j = i+1; j < arr.length; j++) {
minPos = arr[j].compareTo(arr[minPos]) == -1 ? j : minPos;
}
swap(arr, i, minPos);
}
}
private void swap(Comparable[] arr, int i, int minPos) {
Comparable temp = arr[i];
arr[i] = arr[minPos];
arr[minPos] = temp;
}
}
复制代码
测试一下;
package com.cc.strategy;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Cat[] c = {new Cat(3, 3), new Cat(5, 5), new Cat(1, 1)};
Sorter sorter = new Sorter();
sorter.sort©;
System.out.println(Arrays.toString©);
}
}
复制代码
结果:
[Cat{weight=1, height=1}, Cat{weight=3, height=3}, Cat{weight=5, height=5}]
复制代码
Cat类的排序已经完成了,当我们想对Dog也进行排序的话,参照Cat类即可:
package com.cc.strategy;
public class Dog implements Comparable {
int food;
public Dog(int food) {
this.food = food;
}
@Override
public int compareTo(Dog d) {
if (this.food < d.food) {
return -1;
} else if (this.food > d.food) {
return 1;
} else {
return 0;
}
}
@Override
public String toString() {
return “Dog{” +
“food=” + food +
‘}’;
}
}
复制代码
现在还有一个问题,Cat的排序,我们是在Cat类的实现函数compareTo()中根据weight来排的,Cat有两个属性weight和height,当我们想让Cat变成按照height排序的话怎么办呢?修改实现函数compareTo()是肯定不行的,这样一点也不灵活,现在终于轮到策略模式出场了,是的,前面的都不是策略模式,只是铺垫。
让我们来新建一个比较实现类Comparator:
package com.cc.strategy;
public interface Comparator {
int comare(T o1, T o2);
}
复制代码
现在可以开始疑惑了,这个Comparator和刚刚的Comparable有什么区别呢?
答:在Java中,Comparable是排序接口,如果一个类实现了Comparable接口,表示该类支持排序,就像我们在Sorter中实现的,实现类Comparable的对象通过compareTo()方法进行排序,返回1,-1或者0;
而Comparator是比较接口,通常是用于一种比较方法的实现,听到这里可能还是不理解,没关系我们接着看。
在刚刚,Cat是通过weight排序的,为了让Cat能够灵活一些,既可以根据weight排序,也可以根据height排序,我们新建两个比较类:
package com.cc.strategy;
public class CatHeightComparator implements Comparator {
@Override
public int comare(Cat o1, Cat o2) {
if (o1.height < o2.height) {
return 1;
} else if (o1.height > o2.height) {
return -1;
} else {
return 0;
}
}
}
复制代码
package com.cc.strategy;
public class CatWeightComparator implements Comparator {
@Override
public int comare(Cat o1, Cat o2) {
if (o1.weight < o2.weight) {
return -1;
} else if (o1.weight > o2.weight) {
return 1;
} else {
return 0;
}
}
}
复制代码
这两个比较类实现了Comparator的compare()方法,并且分别实现了比较方式,现在改造一下Sorter排序类:
package com.cc.strategy;
public class Sorter {
public void sort(T[] arr, Comparator comparator) {
for (int i = 0; i < arr.length; i++) {
int minPos = i;
for (int j = i+1; j < arr.length; j++) {
minPos = comparator.comare(arr[j], arr[minPos]) == -1 ? j : minPos;
}
swap(arr, i, minPos);
}
}
private void swap(T[] arr, int i, int minPos) {
T temp = arr[i];
arr[i] = arr[minPos];
arr[minPos] = temp;
}
}
复制代码
现在,可以将原来Cat关于Comparable实现类的代码删掉,留下一个干净的对象了,因为排序实现我们放在了CatHeightComparator和CatWeightComparator中:
package com.cc.strategy;
public class Cat {
int weight, height;