一引出问题
场景:有五种水果,每个水果都有sweet(甜度)属性和sour(酸度)属性,我们现在需要对水果按照甜度排序。
将所有水果置于一个ArrayList中,不采用Strategy时,对ArrayList进行封装,添加sort()方法,类图如下:
这种方法有两个主要问题
1)sort()只能在这个类中应用,以后有其他需要排序的类时,需要重新实现排序
2)如果需要更换排序算法,也需要修改代码
3)如果Fruit添加酸度属性,并有按照酸度排序的要求,需要修改代码
二分析问题
为了解决上述的问题,可以将排序算法从数据集合中分离出来,因此引入Strategy模式
Strategy模式
此类问题有一个基本目标:separate things that changes from things that stay the same, 即将变化的部分与不变的部分分离,这样下次修改变化的部分,不变的就不用修改了。排序算法就是这样的一个代表,由于排序算法可能会修改(快排,堆排等),而且会对不同的地方都进行排序,如对多个List进行排序,因此需要把排序算法独立出来,封装成一个单独的类,即Strategy object,此后就可以用这个Strategy object 对其他地方也可以排序。
三解决问题
将排序算法与数据集合分离,解耦。在Java中有两种方法实现排序。
1 实现Comparable接口
Fruit类实现Comparable接口,利用Collections类(java.utils中的一个类,包含一些static的方法)的sort()方法,Collections.sort()按照类的compareTo()方法对ArrayList<Fruit>中的各个对象比较,进行排序。
优点:Collections类封装排序算法,实现排序算法与数据本身分离。
类图如下:
实现代码如下:
Fruit类如下:
public class Fruit implements Comparable<Fruit>{
String name;
int sweet; //甜度
int sour; //酸度
public Fruit(String name, int sweet, int sour){
this.name = name;
this.sweet = sweet;
this.sour = sour;
}
public String toString(){
return name+" sweet- "+sweet +" sour- "+sour;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSweet() {
return sweet;
}
public void setSweet(int sweet) {
this.sweet = sweet;
}
public int getSour() {
return sour;
}
public void setSour(int sour) {
this.sour = sour;
}
@Override
public int compareTo(Fruit o) {
// TODO Auto-generated method stub
return sweet - o.getSweet();
}
}
主函数如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Strategy {
static public void main(String[]args){
List<Fruit>myFruit = new ArrayList<Fruit>();
myFruit.add(new Fruit("orange", 3, 5));
myFruit.add(new Fruit("apple", 4, 3));
myFruit.add(new Fruit("banana", 2, 1));
myFruit.add(new Fruit("pear", 1, 2));
myFruit.add(new Fruit("grape", 5, 4));
//-------------------------------------------------
System.out.println("MyFruit , Before sort : "+myFruit);
Collections.sort(myFruit);
System.out.println("MyFruit , After sweet sort : "+myFruit);
}
}
执行结果如下:
MyFruit , Before sort : [orange sweet- 3 sour- 5, apple sweet- 4 sour- 3, banana sweet- 2 sour- 1, pear sweet- 1 sour- 2, grape sweet- 5 sour- 4]
MyFruit , After sweet sort : [pear sweet- 1 sour- 2, banana sweet- 2 sour- 1, orange sweet- 3 sour- 5, apple sweet- 4 sour- 3, grape sweet- 5 sour- 4]
利用Comparable接口有两个遗留问题:
(1)对类需要修改排序规则,比如我们需要对Fruit类按照酸度排序时,无法实现
(2)对没有实现Comparable接口的类排序时,无法解决
2 实现Comparator接口
实现一个Comparator类,将排序规则再次提取,再次解耦,实现数据集与比较方法的分离。如果需要按照酸度排序时,只需要添加一个类实现Comparator接口,按照酸度排序即可。
类图如下:
代码如下:
甜度排序Comparator
import java.util.Comparator;
class SweetComparator implements Comparator<Fruit>{
@Override
public int compare(Fruit o1, Fruit o2) {
// TODO Auto-generated method stub
return o1.getSweet() - o2.getSweet();
}
}
酸度排序Comparator
import java.util.Comparator;
public class SourComparator implements Comparator<Fruit>{
@Override
public int compare(Fruit o1, Fruit o2) {
// TODO Auto-generated method stub
return o1.getSour() - o2.getSour();
}
}
主函数,分别按照甜度和酸度排序
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Strategy {
static public void main(String[]args){
List<Fruit>myFruit = new ArrayList<Fruit>();
myFruit.add(new Fruit("orange", 3, 5));
myFruit.add(new Fruit("apple", 4, 3));
myFruit.add(new Fruit("banana", 2, 1));
myFruit.add(new Fruit("pear", 1, 2));
myFruit.add(new Fruit("grape", 5, 4));
System.out.println("MyFruit , Before sort : "+myFruit);
Collections.sort(myFruit, new SweetComparator());
System.out.println("MyFruit , After sweet sort : "+myFruit);
//再次将顺序打乱
Collections.shuffle(myFruit);
Collections.sort(myFruit, new SourComparator());
System.out.println("MyFruit , After sour sort : "+myFruit);
}
}
执行结果:
MyFruit , Before sort : [orange sweet- 3 sour- 5, apple sweet- 4 sour- 3, banana sweet- 2 sour- 1, pear sweet- 1 sour- 2, grape sweet- 5 sour- 4]
MyFruit , After sweet sort : [pear sweet- 1 sour- 2, banana sweet- 2 sour- 1, orange sweet- 3 sour- 5, apple sweet- 4 sour- 3, grape sweet- 5 sour- 4]
MyFruit , After sour sort : [banana sweet- 2 sour- 1, pear sweet- 1 sour- 2, apple sweet- 4 sour- 3, grape sweet- 5 sour- 4, orange sweet- 3 sour- 5]
四总结问题
Java中comparator是strategy的完美诠释,将排序算法提取到Collections类中,将比较规则提取到Comparator中,实现数据与排序算法的完全解耦。