05策略模式

05策略模式

在軟件開發中也常常遇到類似的情況,當實現某一個功能存在多種算法或者策略,我們可以根據環境或者條件的不同選擇不同的算法或者策略來完成該功能,如數據排序策略有冒泡排序、選擇排序、插入排序、二叉樹排序等。如果使用多重條件轉移語句實現(即硬編碼),不但使條件語句變得很複雜,而且增加、刪除或更換算法要修改原代碼,不易維護,違背開閉原則。如果採用策略模式就能很好解決該問題。

策略模式的定義與特點

該模式定義了一系列算法,並將每個算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶。策略模式屬於對象行爲模式,它通過對算法進行封裝,把使用算法的責任和算法的實現分割開來,並委派給不同的對象對這些算法進行管理。

策略模式的主要優點如下

  1. 多重條件語句不易維護,而使用策略模式可以避免使用多重條件語句。
  2. 策略模式提供了一系列的可供重用的算法族,恰當使用繼承可以把算法族的公共代碼轉移到父類裏面,從而避免重複的代碼。
  3. 策略模式可以提供相同行爲的不同實現,客戶可以根據不同時間或空間要求選擇不同的。
  4. 策略模式提供了對開閉原則的完美支持,可以在不修改原代碼的情況下,靈活增加新算法。
  5. 策略模式把算法的使用放到環境類中,而算法的實現移到具體策略類中,實現了二者的分離。

其主要缺點如下

  1. 客戶端必須理解所有策略算法的區別,以便適時選擇恰當的算法類。
  2. 策略模式造成很多的策略類。

策略模式的結構與實現

策略模式是準備一組算法,並將這組算法封裝到一系列的策略類裏面,作爲一個抽象策略類的子類。策略模式的重心不是如何實現算法,而是如何組織這些算法,從而讓程序結構更加靈活,具有更好的維護性和擴展性,現在我們來分析其基本結構和實現方法。

模式的結構

策略模式的主要角色如下

  1. 抽象策略(Strategy)類:定義了一個公共接口,各種不同的算法以不同的方式實現這個接口,環境角色使用這個接口調用不同的算法,一般使用接口或抽象類實現。
  2. 具體策略(Concrete Strategy)類:實現了抽象策略定義的接口,提供具體的算法實現。
  3. 環境(Context)類:持有一個策略類的引用,最終給客戶端調用。

代碼實現

原始方法

public class RowWay {
    public static double calc(String op, double paramA, double paramB) {
        if ("+".equals(op)) {
            System.out.println("執行加法...");
            return paramA + paramB;
        } else if ("-".equals(op)) {
            System.out.println("執行減法...");
            return paramA - paramB;
        } else if ("*".equals(op)) {
            System.out.println("執行乘法...");
            return paramA * paramB;
        } else if ("/".equals(op)) {
            System.out.println("執行除法...");
            if (paramB == 0) {
                throw new IllegalArgumentException("除數不能爲0!");
            }
            return paramA / paramB;
        } else {
            throw new IllegalArgumentException("未找到計算方法!");
        }
    }
}

 

抽象方法接口
interface Strategy{
    public double calc(double paramA, double paramB);
}

具體的實現這個接口的策略

 

//加法的具體實現策略
public class AddStrategy implements Strategy {
    @Override
    public double calc(double paramA, double paramB) {
        System.out.println("執行加法策略...");
        return paramA + paramB;
    }
}

 

public class SubStrategy implements Strategy {
    @Override
    public double calc(double paramA, double paramB) {
        System.out.println("執行減法策略...");
        return paramA - paramB;
    }
}

 

//乘法的具體實現策略
public class MultiStrategy implements Strategy {
    @Override
    public double calc(double paramA, double paramB) {
        System.out.println("執行乘法策略...");
        return paramA * paramB;
    }
}

 

public class DivStrategy implements Strategy {
    @Override
    public double calc(double paramA, double paramB) {
        System.out.println("執行除法策略...");
        if (paramB == 0){
            System.out.println("除數不能爲0 ");
            throw new IllegalArgumentException("除數不能爲0!");
        }
        return paramA / paramB;
    }
}

 

調用策略的封裝

//上下文環境的實現
public class Calc {
    private Strategy strategy;
    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    //執行方法
    public static double calc(Strategy strategy, double paramA, double paramB) {
        Calc calc = new Calc();
        calc.setStrategy(strategy);
        return calc.calc(paramA, paramB);
    }


    public double calc(double paramA, double paramB) {
        // doing something
        if (this.strategy == null) {
            throw new IllegalStateException("你還沒有設置計算的策略");
        }
        return this.strategy.calc(paramA, paramB);
    }
}

 

測試

public class StrategyModeTest {
        public static void main(String[] args) {

            Calc calc = new Calc();
            double paramA = 5;
            double paramB = 21;
            double paramC = 1;

            System.out.println("------------- 普通形式 ----------------");
            RowWay row  = new RowWay();
            paramC =RowWay.calc("+",22,33);
            System.out.println(paramC);
            System.out.println("------------ 策略模式  ----------------");
            paramC = Calc.calc(new AddStrategy(),2,2);
            System.out.println(paramC);
            paramC = Calc.calc(new SubStrategy(),2,2);
            System.out.println(paramC);

    }
}

 

測試結果

 

------------- 普通形式 ----------------

執行加法...

55.0

------------ 策略模式  ----------------

執行加法策略...

4.0

執行減法策略...

0.0

策略模式的擴展

在一個使用策略模式的系統中,當存在的策略很多時,客戶端管理所有策略算法將變得很複雜,如果在環境類中使用策略工廠模式來管理這些策略類將大大減少客戶端的工作複雜度

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