在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。如查找、排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;当然也可以将这些查找算法封装在一个统一的方法中,通过if…else…或者case等条件判断语句来进行选择。这两种实现方法我们都可以称之为硬编码,如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。如果我们将这些策略包含在客户端,这种做法更不可取,将导致客户端程序庞大而且难以维护,如果存在大量可供选择的算法时问题将变得更加严重。
下面我们以排序举例子:
首选普及一下最常用的7种排序方法分别是:冒泡、选择、插入、希尔、快速、归并、堆。
咱们以冒泡为例演示:
假如一个int类型的数组的话,好办,直接排就行了,但假设是一个对象呢,根据对象的什么特征比较也不确定,所以我们需要让客户去自己安排比较策略,而我们只需要提供接口,让需要排序的类对象去实现接口就行。
上代码:
比如说是一群猫,要根据高度比较排序:
我们就设计一个比较接口,用于比较任何对象:
package com.jiang;
public interface Comarable {
int comparableTo(Object o);
}
让需要做排序的实体去实现它:
package com.jiang;
public class Cat implements Comarable{
private int height;
private int weight;
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public Cat(int height, int weight) {
super();
this.height = height;
this.weight = weight;
}
@Override
public String toString() {
return "Cat [height=" + height + ", weight=" + weight + "]";
}
//定义一个自己的成员变量:
//private Comparator comparator=new CatHeightCompartor();
private Comparator comparator=new CatWeightComparator();
public Comparator getComparator() {
return comparator;
}
public void setComparator(Comparator comparator) {
this.comparator = comparator;
}
//比较大小的实现:
@Override
public int comparableTo(Object o) {
//不写死:4
//return new CatHeightCompartor().compare(this, o);
//利用自己设置的成员变量,给什么比较什么
return comparator.compare(this, o);
/*if(o instanceof Cat){
Cat c=(Cat)o;
if(this.getHeight()>c.getHeight()) return 1;
else if(this.getHeight()<c.getHeight()) return -1;
else return 0;
}
return -100;*/
}
}
而在上面代码中我们将Cat定义一个自己的成员变量:private Comparator comparator=new CatWeightComparator();
这样一来我们就可以用多态的方式,将这个成员变量去指向想要的比较策略,从而得到不同的排序,续而有以下以高度比较还是以重量比较的类:
package com.jiang;
public class CatHeightCompartor implements Comparator{
@Override
public int compare(Object o1, Object o2) {
Cat c1=(Cat)o1;
Cat c2=(Cat)o2;
if(c1.getHeight()>c2.getHeight()) return 1;
else if(c1.getHeight()<c2.getHeight()) return -1;
else return 0;
}
}
package com.jiang;
public class CatWeightComparator implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Cat c1=(Cat)o1;
Cat c2=(Cat)o2;
if(c1.getHeight()>c2.getHeight()) return 1;
else if(c1.getHeight()<c2.getHeight()) return -1;
else return 0;
}
}
这样:private Comparator comparator=new CatWeightComparator();就是以高度来排序,private Comparator =new CatWeightComparator就是以重量来比较排序,而要以什么方式来比较,这个比较策略交给客户去实现,然后维护到要比较的实体中去就好了。
接下来我们实现比较逻辑,为了代码公共都能用,采用Object或者泛型的方式来处理:
package com.jiang;
public class DataSorter {
public void sort(Comarable[] a){
for(int i=0;i<a.length;i++){
for(int j=0;j<a.length-i-1;j++){
/*Comarable o1=(Comarable)a[j];
Comarable o2=(Comarable)a[j+1];*/
Object temp=null;
if(a[j].comparableTo(a[j+1])==1){
a[j+1]=a[j];
a[j]=(Comarable) temp;
temp=a[j+1];
}
}
}
/*for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}*/
}
/**
* 调用此方法便可遍历 输出排序后的对象
* @param a
*/
public void p(Object[]a){
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
}
这样一来,我们只要知道一个对象去实现比较排序的接口,自定义一个比较策略,就可以灵活的为其排好序。
同理现在如果有个dog类要为其按照食量来排序,那么:
package com.jiang;
public class Dog implements Comarable{
private int food;
public int getFood() {
return food;
}
public void setFood(int food) {
this.food = food;
}
public Dog(int food) {
super();
this.food = food;
}
private DogHeight dogHight=new DogHeight();
public DogHeight getDogHight() {
return dogHight;
}
public void setDogHight(DogHeight dogHight) {
this.dogHight = dogHight;
}
@Override
public String toString() {
return "Dog [food=" + food + "]";
}
@Override
public int comparableTo(Object o) {
/*if(o instanceof Dog){
Dog d=(Dog)o;
if(this.food>d.getFood()) return 1;
else if(this.food<d.getFood()) return -1;
else return 0;
}
else return -100;
}*/
return dogHight.compare(this, o);
}
}
让dog去实现比较,在在里面维护一个dogHight属性(这里应该是叫foot才对哈,名字而已),
package com.jiang;
public class DogHeight implements Comparator{
@Override
public int compare(Object o1, Object o2) {
Dog d1=(Dog)o1;
Dog d2=(Dog)o2;
if(d1.getFood()>d2.getFood()) return 1;
else if(d1.getFood()<d2.getFood()) return -1;
else return 0;
}
}
(同理这个类应该叫dogFoot才好)
最后运行:
package com.jiang;
public class Test {
public static void main(String[] args) {
int []a={2,3,4,6,8,7,};
Cat[]c={new Cat(1,3),new Cat(2,4),new Cat(4,8)};
Dog[]d={new Dog(20),new Dog(30),new Dog(80)};
//排序:
DataSorter ds=new DataSorter();
/*ds.sort(d);
ds.p(d);*/
ds.sort(d);
//打印出信息:
ds.p(d);
}
}