策略模式在應用中的實踐

2022-06-20 12:05:35

行為模式有一種模式叫策略模式(Strategy Pattern),一個類的行為或其演演算法可以在執行時更改。在策略模式中,我們建立表示各種策略的物件和一個行為隨著策略物件改變而改變的 context 物件。策略物件改變 context 物件的執行演演算法。

意圖:定義一系列的演演算法,把它們一個個封裝起來, 並且使它們可相互替換。

主要解決:在有多種演演算法相似的情況下,使用 if...else 所帶來的複雜和難以維護。何時使用:一個系統有許多許多類,而區分它們的只是他們直接的行為。

如何解決:將這些演演算法封裝成一個一個的類,任意地替換。關鍵程式碼:實現同一個介面。 

優點:

1、演演算法可以自由切換。

2、避免使用多重條件判斷。

3、擴充套件性良好。

缺點:

1、策略類會增多。

2、所有策略類都需要對外暴露。

使用場景: 

1、如果在一個系統裡面有許多類,它們之間的區別僅在於它們的行為,那麼使用策略模式可以動態地讓一個物件在許多行為中選擇一種行為。2、一個系統需要動態地在幾種演演算法中選擇一種。3、如果一個物件有很多的行為,如果不用恰當的模式,這些行為就只好使用多重的條件選擇語句來實現。注意事項:如果一個系統的策略多於四個,就需要考慮使用混合模式,解決策略類膨脹的問題。

應用案例:

實現按任務型別執行型別相對應的任務,不同的任務對應的是不同的演演算法。

1. 定義一個介面或抽象類

package com.tiny.strategy;
/**

* BaseTask
*
* @author tianya
* @date 2020/11/29
*/
public abstract class BaseTask {
abstract void run();
}

 

2. 定義幾組實現的類

package com.tiny.strategy;
/**
 * WeekTask
 *
 * @author tianya
 * @date 2020/11/29
 */
public class WeekTask extends BaseTask {
    @Override
    void run() {
        System.out.println("run weekTask");
    }
}


package com.tiny.strategy;
/**
 * DayTask
 *
 * @author tianya
 * @date 2020/11/29
 */
public class DayTask extends BaseTask {
    @Override
    void run() {
        System.out.println("run dayTask");
    }
}

 

3. 定義一個工廠,根據型別去實現對應的任務。

package com.tiny.strategy;
/**
 * TaskFactory
 *
 * @author tianya
 * @date 2020/11/29
 */
public interface TaskFactory {
    /**
     * 獲取Task
     *
     * @param type
     * @return
     */
    BaseTask getTask(String type);
}


package com.tiny.strategy;
import java.util.HashMap;
import java.util.Map;
/**
 * TaskFactoryImpl
 *
 * @author tianya
 * @date 2020/11/29
 */
public class TaskFactoryImpl implements TaskFactory {
    private static final Map<String, BaseTask> taskMap = new HashMap(2);
    public BaseTask getTask(String type) {
        if ("day".equals(type)) {
            return new DayTask();
        }
        if ("week".equals(type)) {
            return new WeekTask();
        }

        throw new IllegalArgumentException("task type not found");
    }
}

這裡為了簡單工廠方法直接用的if,這裡可以定義一個map去替代 if。

4.呼叫入口。

package com.tiny.strategy;
/**
 * App
 *
 * @author tianya
 * @date 2020/11/29
 */
public class App {
    public static void main(String[] args) {
        TaskFactory taskFactory = new TaskFactoryImpl();
        BaseTask task = taskFactory.getTask("day");
        task.run();
        task = taskFactory.getTask("week");
        task.run();
    }
}

 

程式碼的github 地址:

https://github.com/tianyaxiang/ApplicationArchitecture/tree/master/strategy

案例中生成策略類我們用了工廠模式,這樣把變化點集中到了工廠方法裡,有新增的任務修改工廠類就好了。這裡有個優化的點,可以利用Spring 實現一個動態的工廠,如果有需求的話。​