1. 程式人生 > >java設計模式-策略模式

java設計模式-策略模式

temp return private 數組排序 寫法 冒泡 有一種 eth RF

背景:將一個數組排序,並且打印; 1.下面使用選擇排序、和冒泡排序來寫:                        
public class Test {

    public static void main(String[] args) {
        int a[] = {9, 5, 3, 7, 1, 10};
        DataSorter.sort(a);
        DataSorter.p(a);
    }

}

DataSort:

package com.cy.dp.strategy;

public class DataSorter {
    
    
/** * 選擇排序法 * @param a public static void sort(int[] a) { int temp; for(int i=0; i<a.length; i++){ for(int j=i+1; j<a.length; j++){ if(a[i]>a[j]){ temp = a[i]; a[i] = a[j]; a[j] = temp; } } } }
*/ /** * 冒泡排序法 * @param a */ public static void sort(int[] a) { int temp; for(int i=a.length; i>0; i--){ for(int j=0; j<i-1; j++){ if(a[j]>a[j+1]){ temp = a[j]; a[j] = a[j+1]; a[j
+1] = temp; } } } } public static void p(int[] a) { for(int i=0; i<a.length; i++){ System.out.print(a[i] + " "); } System.out.println(); } }

但是上面有個問題:

sort方法裏面現在只能排序int類型的;

如果我想對於float類型進行排序,怎麽辦?--可以重載方法sort(float[] a);

如果想對於double類型的進行排序,怎麽辦?--再重載一個double參數的;

因為sort方法裏面a[j]和a[j+1]的int類型的,能直接比較,這還好辦,但是如果現在想DataSorter對貓、狗、Car、等等...進行排序,怎麽辦?

2.對所有對象的數組都能夠進行排序 定義比較接口Comparable:
//實現這個接口的類,表示是可以比較的
public interface Comparable {
    
    public int compareTo(Object o);
}

DataSort可以排序任何類(該類實現Comparable接口),打印任何類;

寫完一次排序方法,再也不用改變了;

package com.cy.dp.strategy;

public class DataSorter {
    
    /**
     * 冒泡排序法,排序任何類型,Object類型
     * 假設Object[]裏面對象都實現了Comparable接口,都是可以比較大小的;
     * @param a
     */
    public static void sort(Object[] a) {
        Object temp;
        for(int i=a.length; i>0; i--){
            for(int j=0; j<i-1; j++){
                Comparable o1 = (Comparable)a[j];
                Comparable o2 = (Comparable)a[j+1];
                if(o1.compareTo(o2) > 0){
                    temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                }
            }
        }
    }

    public static void p(Object[] a) {
        for(int i=0; i<a.length; i++){
            System.out.print(a[i] + " ");
        }
        System.out.println();
    }
    
    
}

Cat實現Compareble接口:

技術分享圖片
package com.cy.dp.strategy;

public class Cat implements Comparable{
    private int height;
    private int weight;
    
    public Cat(int height, int weight) {
        super();
        this.height = height;
        this.weight = 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;
    }
    
    @Override
    public int compareTo(Object 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;    //簡單寫法,如果o不是cat,表示出錯;實際要拋異常
    }
    
    
    @Override
    public String toString() {
        return height + "|" + weight;
    }
}
View Code

Dog實現Comparable接口:

技術分享圖片
package com.cy.dp.strategy;

public class Dog implements Comparable{
    private int food;
    
    public Dog(int food) {
        super();
        this.food = food;
    }
    public int getFood() {
        return food;
    }
    public void setFood(int food) {
        this.food = food;
    }
    
    //對狗按照飯量大小進行排序
    @Override
    public int compareTo(Object o) {
        Dog d = (Dog) o;
        if(this.food > d.getFood()) return 1;
        else if(this.food < d.getFood()) return -1;
        else return 0;
    }
    @Override
    public String toString() {
        return "Dog [food=" + food + "]";
    }
    
}
View Code

測試:

public class Test {

    public static void main(String[] args) {
        Cat a[] = {new Cat(5,5), new Cat(3,3), new Cat(1,1)};
        DataSorter.sort(a);
        DataSorter.p(a);
        
        Dog d[] = {new Dog(3), new Dog(1), new Dog(5), new Dog(4)};
        DataSorter.sort(d);
        DataSorter.p(d);
    }

}

輸出

1|1 3|3 5|5 
Dog [food=1] Dog [food=3] Dog [food=4] Dog [food=5] 

現在DataSort類可以對任何實現Comparable的類進行排序了,但是上面還是存在問題:

當前比較貓的大小的時候,只是根據貓的height,假如哪天要根據貓的weight、或者胡子的長度,或者別的來比較大小呢?怎麽辦?

也就是說現在Cat等實現的compareTo方法只能有一種實現,當還有其他不確定的實現時,這時候該怎麽設計?

3.實現Comparable接口的類,其compareTo方法,交給具體的比較策略,讓它去實現; 而不是說我自己固定寫死; Comparator:
//比較器
public interface Comparator {
    
    int compare(Object o1, Object o2);
}

貓的高度比較器:

//兩只貓之間根據高度比較大小的  比較器
public class CatHeightComparator 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;
    }
}

貓的重量比較器:

//兩只貓之間根據重量比較大小的  比較器
public class CatWeightComparator implements Comparator {

    @Override
    public int compare(Object o1, Object o2) {
        Cat c1 = (Cat) o1;
        Cat c2 = (Cat) o2;
        if(c1.getWeight()>c2.getWeight()) return -1;
        else if(c1.getWeight() < c2.getWeight()) return 1;
        else return 0;
    }

}

Cat類下面compareTo方法交給具體的比較器來實現:

package com.cy.dp.strategy;

public class Cat implements Comparable{
    private int height;
    private int weight;
    //默認是高度的比較器
    //private Comparator comparator = new CatHeightComparator();
    private Comparator comparator = new CatWeightComparator();
    
    public Cat(int height, int weight) {
        super();
        this.height = height;
        this.weight = weight;
    }
    public Comparator getComparator() {
        return comparator;
    }
    public void setComparator(Comparator comparator) {
        this.comparator = comparator;
    }
    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;
    }
    
    @Override
    public int compareTo(Object o) {
        
        return comparator.compare(this, o);
    
    }
    
    
    @Override
    public String toString() {
        return height + "|" + weight;
    }
}

測試程序:

public class Test {

    public static void main(String[] args) {
        Cat a[] = {new Cat(5,5), new Cat(3,3), new Cat(1,1)};
        //Dog a[] = {new Dog(3), new Dog(1), new Dog(5), new Dog(4)};
        DataSorter.sort(a);
        DataSorter.p(a);
        
    }

}

輸出:5|5 3|3 1|1

4.看看JDK是怎麽做的:我們使用jdk裏面的Comparable接口、Comparator接口:

Cat:

package com.cy.dp.strategy;

public class Cat implements java.lang.Comparable<Cat>{
    private int height;
    private int weight;
    //默認是高度的比較器
    private java.util.Comparator<Cat> comparator = new CatHeightComparator();
    
    public Cat(int height, int weight) {
        super();
        this.height = height;
        this.weight = weight;
    }
    public java.util.Comparator<Cat> getComparator() {
        return comparator;
    }
    public void setComparator(java.util.Comparator<Cat> comparator) {
        this.comparator = comparator;
    }
    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;
    }

    @Override
    public int compareTo(Cat o) {
        return comparator.compare(this, o);
    }
    
    @Override
    public String toString() {
        return height + "|" + weight;
    }
    
}

根據高度的比較器CatHeightComparator:

//兩只貓之間根據高度比較大小的  比較器
public class CatHeightComparator implements java.util.Comparator<Cat> {

    @Override
    public int compare(Cat c1, Cat c2) {
        if(c1.getHeight()>c2.getHeight()) return 1;
        else if(c1.getHeight() < c2.getHeight()) return -1;
        else return 0;
    }
}

DataSort也改一下,就是使用java.lang.Comparable,其他不變:

package com.cy.dp.strategy;
import java.lang.Comparable;

public class DataSorter {
    
    /**
     * 冒泡排序法,排序任何類型,Object類型
     * 假設Object[]裏面對象都實現了Comparable接口,都是可以比較大小的;
     * @param a
     */
    public static void sort(Object[] a) {
        Object temp;
        for(int i=a.length; i>0; i--){
            for(int j=0; j<i-1; j++){
                Comparable o1 = (Comparable)a[j];
                Comparable o2 = (Comparable)a[j+1];
                if(o1.compareTo(o2) > 0){
                    temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                }
            }
        }
    }

    public static void p(Object[] a) {
        for(int i=0; i<a.length; i++){
            System.out.print(a[i] + " ");
        }
        System.out.println();
    }
    
    
}

測試代碼:

public class Test {

    public static void main(String[] args) {
        Cat a[] = {new Cat(5,5), new Cat(3,3), new Cat(1,1)};
        //Dog a[] = {new Dog(3), new Dog(1), new Dog(5), new Dog(4)};
        DataSorter.sort(a);
        DataSorter.p(a);
        
    }

}

輸出:1|1 3|3 5|5

完美和JDK融合;基本模擬了JDK裏面的Comparable接口和Comparator接口;

5.而且其實不用自己寫DataSort,用Arrays就行了:

public static void main(String[] args) {
        Cat a[] = {new Cat(5,5), new Cat(3,3), new Cat(1,1)};
        //Dog a[] = {new Dog(3), new Dog(1), new Dog(5), new Dog(4)};
        //DataSorter.sort(a);
        
        java.util.Arrays.sort(a);  //Arrays.sort(Object[] a)   註:a必須實現Comparable接口
        DataSorter.p(a);
    }

也可以:

public static void main(String[] args) {
        Cat a[] = {new Cat(5,5), new Cat(3,3), new Cat(1,1)};
        //Dog a[] = {new Dog(3), new Dog(1), new Dog(5), new Dog(4)};
        //DataSorter.sort(a);
        //java.util.Arrays.sort(a);
        
        java.util.Arrays.sort(a, new java.util.Comparator<Cat>(){
            @Override
            public int compare(Cat o1, Cat o2) {
                return o1.getHeight()>o2.getHeight()?1
                        :o1.getHeight()<o2.getHeight()?-1
                        :0;
            }
        });
        
        DataSorter.p(a);
    }

小結:

策略模式就是說,當我進行比較大小的時候,我定義一個策略的比較器,然後由具體的比較策略來決定誰大誰小;

使用例子,比如:

1.封裝一下商場的打折策略;

  周六打折,過年打折,兩種加在一塊就打折,等等。所以打折策略最好不要寫死它,因為將來可能有不能確定的各種各樣的打折策略;所以最好把打折策略定義成一個可以擴展的內容;這就是策略模式;

2.封裝一下坦克的發射炮彈的策略;

  有的時候打一發,有的時候打多發,等等,具體由我發射炮彈的策略決定;

java設計模式-策略模式