從簡單模式到策略模式

  前面我們談了簡單工廠模式,下面我們談一下策略模式。

策略模式定義了一系列的算法,並將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立於使用它的客戶而獨立變化。

它的優點有:

  1、 提供了一種替代繼承的方法,而且既保持了繼承的優點(代碼重用)還比繼承更靈活(算法獨立,可以任意擴展)

  2、 避免程序中使用多重條件轉移語句,使系統更靈活,並易於擴展。

  3、 遵守大部分GRASP原則和常用設計原則,高內聚、低偶合。

  缺點:

因爲每個具體策略類都會產生一個新類,所以會增加系統需要維護的類的數量

我們以商場收銀來說明一下這個模式。

  商場收銀軟件需求很簡單,營業員根據客戶所購買商品的單價和數量,向客戶收費。

  也許有些人會這麼想,這個很簡單,接受用戶輸入的的單價和數量,把他們相乘不就可以了嘛。當然,。,那當然可以。那如果商場對某些商品進行打折活動呢。也許你會說,那還不簡單,讓用戶輸入打幾折不就行了嘛。計算總價時在原來的基礎上乘以折扣就是客戶的收費了。也許這個時候,你想到了封裝,抽象,或者用我們以前的簡單工廠模式來解決這個問題。代碼如下:

 1;我們先寫一個現金收費抽象類。

  public abstract class CashSuper {

   public abstract double acceptCash(double money);

}

2:正常收費子類,繼承現金收費抽象類:

public class CashNormal extends CashSuper {

   public double acceptCash(double money){

       return money;

   }

}

 3:打折收費子類,繼承現金收費抽象類

public class CashRebate extends CashSuper {

private double moneyRebate=0.0;//折扣

    @Override

    public double acceptCash(double money) {

        // TODO Auto-generated method stub

        return money*moneyRebate;

    }

    public CashRebate(String moneyRebate){

        this.moneyRebate=Double.parseDouble(moneyRebate);

    }

 

}

4:返利收費子類,如果客戶滿300100

 public class CashReturn extends CashSuper {

    private double moneyCondition=0;//返利條件

    private double moneyReturn=0;//返利

    public CashReturn(String moneyCondition,String moneyReturn ){

    this.moneyCondition=Double.parseDouble(moneyCondition);

    this.moneyReturn=Double.parseDouble(moneyReturn);

    }

    public double acceptCash(double money){

        double result=money;

        if(money>=moneyCondition)

            result=money-Math.floor(money/moneyCondition)*moneyReturn;

        return result;

    }

}

5:現金收費工廠類:

public class CashFactory {

    public static CashSuper createCashAccept(int type ){

        CashSuper cs=null;

        switch(type){

        case 1:

            //1表示正常收費

             cs=new CashNormal();

             break;

        case 2:

            //滿300100

            CashReturn cr1=new CashReturn("300","100");

            cs=cr1;

            break;

        case 3:

            //8

            CashRebate cr2=new CashRebate("0.8");

            cs=cr2;

            break;

           

        }

        return cs;

    }

 

}

6:測試類主要實例化工廠類,接受單價和數量,還有折扣和返利。

我們想想這是最好的辦法嗎?我們前面講過,簡單工廠模式雖然也能解決這類問題,但是我們知道這個模式只是解決對象的創建問題。而商場收銀軟件也許有可能會經常更改打折和返利,那我們是不是都要改動工廠呢?仔細想想,它打折和返利,只是算法的更改。爲什麼我們不用策略模式呢?

策略模式定義了算法家族,分別封裝起來 ,讓他們之間可以互相替換,此模式讓算法的變化,不會影響到使用算法的客戶。

下面我們用策略模式和簡單工廠的結合解決這個問題:

原來寫的CashSuper,CashNormal,CashRebate,CashReturn都不用改了,我們再加一個類:

1cashContext類,用一個ConcreteStrategy來配置,維護一個對Strategy對象的引用。

public class CashContext {

    private CashSuper cs=null;

    public CashContext(int type){

        switch(type){

        case 1:

            //正常收費

            CashNormal cs1=new CashNormal();

            cs=cs1;

            break;

        case 2:

            //滿300返回100

            CashReturn cr2=new CashReturn("300","100");

            cs=cr2;

            break;

        case 3:

            CashRebate cr3=new CashRebate("0.8");

            cs=cr3;

            break;

           

        }

    }

    public double GetResult(double money){

        return cs.acceptCash(money);

    }

 

}

這樣就可以了,其他的任務交給客戶端就行了。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章