Strategy設計模式

Strategy策略模式是屬於設計模式中對象行爲型模式,主要是定義一系列的算法,把這些算法一個個封裝成單獨的類.我們達到了在運行期間,可以自由切換算法的目的。實際整個Strategy的核心部分就是抽象類(或者接口)的使用,使用Strategy模式可以在用戶需要變化時,修改量很少,而且快速.一直有點糊塗的地方就是factory&strategy,實際上StrategyFactory有一定的類似,Strategy相對簡單容易理解,並且可以在運行時刻自由切換Factory重點是用來創建對象

 

設計模式就是把簡單的東西複雜化,但是有理有據,看你將來在那個方向做擴展,那麼就會在那個方向上複雜化,等等,農場生小母牛,那類與類之間的關係太簡單了,感受不到系統之間的精妙的結構的樂趣.設計模式可以讓你感受到這纔是面向對象的樂趣精華所在!

 

設計模式筆記上的例子比較好,這裏拿過來爲以後的理解做鋪墊。

 

TextStrategy是個抽象類,內含抽象方法:replacelinuxstrategy,windowsstrategy繼承這個抽象類,同時各自實現方法replace,textCharChange調用textStrategy類中的replace方法進行使用,

 

TextStrategy抽象類的結構:

public abstract classTextStrategy {

    protected String text;

    public TextStrategy(String text) {

        this.text = text;

    }

    public abstract String replace();

} 

Linux的實現策略:

public classLinuxStrategy extends TextStrategy {

   publicLinuxStrategy(String text) {//構造方法

        super(text);

    }

   public String replace() {//實現的具體方法,這纔是核心

        preOperation();

        System.out.println(text =text.replaceAll("@r@n", "@n"));

        postOperation();

        return text;

    } } 

Windows實現策略:

public classWindowsStrategy extends TextStrategy {

    public WindowsStrategy(String text) {

        super(text);

    }

    public String replace() {

        startOperation();

        System.out.println(text =text.replaceAll("@n", "@r@n"));

        endOperation();

        return text;

    }}

整合在一起使用的類:

public classTextCharChange {

   public static voidreplace(TextStrategy strategy) {//傳策略的參數,直接調用,這兒很巧妙!!

        strategy.replace();

   } }

測試類:

public class Main {

    public static void main(String[] args) {

        String linuxText =  "This is a test text!!@n Oh! LineReturn!!@n";

        String windowsText = "This is atest text!!@r@n Oh! Line Return@r@n";

       TextCharChange.replace( new WindowsStrategy(linuxText));//直接調用就行!

        System.out.println();

  TextCharChange.replace( newLinuxStrategy(windowsText));

    }}


 

strategy模式的結構圖,三個具體策略的實現類,一個抽象類或接口,另外一個整合使用的類,直接調用整合後的類即可~~

 以上是strategy模式筆記比較簡單的用法,但是看sp學習的話,馬老師給出了一個很複雜的例子,有點迷糊,沒具體操作。。下次再寫吧,或者就不寫了,其實也很簡單,他的流程是這樣的:

首先用一般的sort方法,想着sort的複用而讓需要排序的類:cat,dag實現comparable接口,實現comparTo方法,通過這個方法對這個類的兩個對象比較大小,爲了實現對同一類的不同屬性的大小的比較,而對每個類生成多個比較策略類:CatHeightComparator,CatWeightComparator,這兩個比較策略使用時可以隨時調用。


分析了下sp中講到的例子,對cat對象比較大小,總共有兩個接口:comparable,comparator,其中comparable中方法爲:compareTo(0)comparator方法:compare(0,0),cat實現了comparable接口,實現compareTo()方法時,使用了compartor.compare()方法,及動態調用需要用到的比較策略:heighe,or weighte比較策略。HeightCompareWeightCompare都實現了compartor接口,實現了compare方法。dataSorter類對數組中的所有對象進行sort操作。test是測試類。




具體代碼如下:

兩個接口的就省了,寫cat的實現:

public class Catimplements java.lang.Comparable<Cat> {

privateint height;

privateint weight;

//privateComparator comparator = new CatHeightComparator();

privatejava.util.Comparator<Cat> comparator = new CatHeightComparator();//此處已經賦值了,不如第一個例子中的給的動態性強

public Cat(Comparator comparator, int height, int weight) {//這樣就可以了。。
super();
this.comparator = comparator;
this.height = height;
this.weight = weight;
}

@Override

publicString toString() {//便於對象的輸出,若沒有的話,只會輸出對象在內存中的引用,是一串引用代碼;

returnheight + "|" + weight;}

@Override

publicint compareTo(Cat o) {//調用comparator的compare方法,這裏如上一個例子中的textChartChange中的replace方法一樣,但是此處調用不很靈活

return comparator.compare(this, o);//可以再爲對像初始化時,傳一個比較器接口,然後進行比較~

}}

HeightCompare實現:weightCompare省掉。

public classCatHeightComparator implements java.util.Comparator<Cat> {

@Override

publicint compare(Cat o1, Cat o2) {//真正比較策略的實現,將方法封裝成類,方便動態調用而不用該代碼;

Catc1 = (Cat)o1;

Catc2 = (Cat)o2;

if(c1.getHeight()> c2.getHeight()) return 1;

elseif(c1.getHeight() < c2.getHeight()) return -1;

return0;

}}

DataSort實現:

public classDataSorter {

public static voidsort(Object[] a) {

for(inti=a.length; i>0; i--) {

for(intj=0; j<i-1; j++) {

Comparableo1 = (Comparable)a[j];

Comparableo2 = (Comparable)a[j+1];

if(o1.compareTo(o2)== 1) {//真正用的地方!實際上,compareTo方法調用了cat內的comparetor對象的compare方法;

swap(a,j , j+1);//工具方法

}}}}

privatestatic void swap(Object[] a, int x, int y) {//注意參數的傳遞,此處要有數組a ,不然起不到換位置的作用!

Objecttemp = a[x];

a[x]= a[y];

a[y]= temp;}

}

Test類實現:

public class Test {

publicstatic void main(String[] args) {

Cat[] c = { new Cat(new CatWeightComparator(), 1, 2),//動態傳比較的屬性值過來,這樣就可以了!

new Cat(new CatWeightComparator(), 27, 1),
new Cat(new CatWeightComparator(), 22, 3) };
DataSorter.sort(a);//直接調用dataSorter的sort方法,sort中調用comparable對象的compareTo方法,compareTo方法實際上調用的是comparable對象中comparetor對象的compare()方法,所以真正實現在comparetor實現類的compare方法中!

DataSorter.p(a);//打印出結果

}}

這個比上面那個例子複雜在:cat本身也是一個實現了comparable接口的類,這樣就跟compartor有點混淆了!其實真正的含義有兩點:

1.實現comparable對象的比較,並且做到datasort sortor方法的可重用性;

2.對同一comparable對象的不同比較方法的實現,並且用動態調用的方式使用;(當然這裏面沒有例子以做的好,因爲compartor對象是寫死在cat類裏的,最好的是在使用時,通過參數傳過來!)

3.與State一樣,例子中完美的面向對象的思維,用TextCharChange完美的把接口及其實現封裝起來,用的時候直接提供TextCharChange就行!贊一個!!而且方法名稱都一樣:replace.不會像後面那個例子那樣容易混淆!當然後面的例子也有他的原因,因爲他是要封裝整個DataSorter類及其sorter方法達到最好的複用性,所以首先要對外提供一個comparable的接口的參數傳遞,使得實現這個接口的所有的類都能調用這個方法進行sort,然後就涉及到,實現類可以調用方法進行比較了,但是真正的比較過程與簡單的數據類型又不相同,因爲是類的比較,有會考慮比較那個屬性?爲了提供更好的多態或者擴展性,就要對外提供一個很比較方法的策略參數的傳值:CatWeightCompartor()類實現了對重量的比較的策略,所以傳遞這個類的對象可以實現這種比較策略,同理,相同的策略是要實現於統一的接口的,才能保證被接受這個參數的方法使用!所以,catweightcompartor實現了compartor接口!

所以,仔細分析才知道,實際上是有兩層策略(sort,compareTo),每一層的使用都會用到接口.sort爲了實現對comparable的對象的比較,comparTo爲了實現對同一對象的多種不同的比較方式!


發佈了66 篇原創文章 · 獲贊 9 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章