行為型模式:策略模式


LieBrother原文
行為型模式:策略模式

景

十一大行為型模式之五:策略模式。

簡介

姓名 :策略模式

英文名 :Strategy Pattern

價值觀 :集計謀於一身

個人介紹
Define a family of algorithms,encapsulate each one,and make them interchangeable.
定義一組算法,將每個算法都封裝起來,並且使它們之間可以互換。
(來自《設計模式之禪》)

你要的故事

先看一張拍得不好看的圖片

洗衣機面板

每天上完班回到家第一件事情是干啥?有人一進門就躺在沙發上閉目養神、有人一進門躺在沙發上玩手機、有人一進門就陪自己的小寵物玩等等。而我進門第一件事就是洗澡,洗完澡很容易就把一整天的疲憊感給消除掉,然后就可以開始美好的下班時光。現實沒那么美好,洗完澡后還要洗衣服,大學手洗了 4 年的衣服,一出來工作,宿舍第一必需品就是洗衣機。細看洗衣機,有很多種洗衣類型,比如:標准、大物、快洗、輕柔。洗衣類型的區別在於洗衣服的過程不一樣,洗衣過程包括有浸泡、洗滌、漂洗、脫水,還有洗衣服的時間也不一樣。細想可以發現這 4 種洗衣類型其實是洗衣服的 4 種不同的策略,也即是 4 種不同的算法。根據這個思路,我們可以用代碼實現它,定義一個接口 WashingStrategy 定義洗衣服類型,而這些類型都有各自的洗衣過程,比如標准洗衣類型就包括浸泡、洗滌、漂洗、脫水,而快洗則只包括洗滌、漂洗、脫水。而我們洗衣服則需要選擇某個洗衣類型后,洗衣機就開始工作了。過程如下代碼所示。

public class StrategyTest {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              

    public static void main(String[] args) {
        WashingStrategy washingStrategy = new StandardWashingStrategy();
        WashingMachine washingMachine = new WashingMachine(washingStrategy);
        washingMachine.washingClothes();
    }

}

/**
 * 洗衣類型
 */
interface WashingStrategy {
    void washing();
}

/**
 * 洗衣機
 */
class WashingMachine {
    private WashingStrategy washingStrategy;

    public WashingMachine(WashingStrategy washingStrategy) {
        this.washingStrategy = washingStrategy;
    }

    public void washingClothes() {
        this.washingStrategy.washing();
    }
}

/**
 * 標准
 */
class StandardWashingStrategy implements WashingStrategy{

    @Override
    public void washing() {
        System.out.println("標准流程:");
        System.out.println("[浸泡] 10 分鍾");
        System.out.println("[洗滌] 2 次,每次 15 分鍾");
        System.out.println("[漂洗] 1 次,每次 10 分鍾");
        System.out.println("[脫水] 5 分鍾");
        System.out.println("總共耗時:55 分鍾");
    }
}

/**
 * 快洗
 */
class QuickWashingStrategy implements WashingStrategy {

    @Override
    public void washing() {
        System.out.println("快洗流程:");
        System.out.println("[洗滌] 1 次,每次 10 分鍾");
        System.out.println("[漂洗] 1 次,每次 10 分鍾");
        System.out.println("[脫水] 5 分鍾");
        System.out.println("總共耗時:25 分鍾");
    }
}

/**
 * 大物
 */
class BigClothesWashingStrategy implements WashingStrategy {

    @Override
    public void washing() {
        System.out.println("大物流程:");
        System.out.println("[浸泡] 30 分鍾");
        System.out.println("[洗滌] 3 次,每次 15 分鍾");
        System.out.println("[漂洗] 2 次,每次 10 分鍾");
        System.out.println("[脫水] 5 分鍾");
        System.out.println("總共耗時:100 分鍾");
    }
}

/**
 * 輕柔
 */
class SoftWashingStrategy implements WashingStrategy {

    @Override
    public void washing() {
        System.out.println("輕柔流程:");
        System.out.println("[浸泡] 10 分鍾");
        System.out.println("[漂洗] 2 次,每次 15 分鍾");
        System.out.println("[脫水] 5 分鍾");
        System.out.println("總共耗時:45 分鍾");
    }
}

標准流程:
[浸泡] 10 分鍾
[洗滌] 2 次,每次 15 分鍾
[漂洗] 1 次,每次 10 分鍾
[脫水] 5 分鍾
總共耗時:55 分鍾

是不是感覺策略模式很簡單呢?上面代碼就是完整的策略模式示例,是不是感覺有些問題,這 4 種洗衣類型對象完全暴露給了用戶,這也是策略模式的缺點。往往策略模式不會單獨使用,會和其他設計模式一起使用,比如和簡單工廠模式一起使用就可以解決這個對外暴露對象的問題,看下面代碼。

/**
 * 洗衣類型選擇
 */
class WashingFactory {

    public static WashingStrategy getWashingStrategy(String type) {
        if ("Quick".equals(type)) {
            return new QuickWashingStrategy();
        }
        if ("BigClothes".equals(type)) {
            return new BigClothesWashingStrategy();
        }
        if ("Soft".equals(type)) {
            return new SoftWashingStrategy();
        }
        return new StandardWashingStrategy();
    }
}

public class StrategyTest {

    public static void main(String[] args) {
        WashingStrategy washingStrategy2 = WashingFactory.getWashingStrategy("Soft");
        WashingMachine washingMachine2 = new WashingMachine(washingStrategy2);
        washingMachine2.washingClothes();
    }
}

打印結果:
輕柔流程:
[浸泡] 10 分鍾
[漂洗] 2 次,每次 15 分鍾
[脫水] 5 分鍾
總共耗時:45 分鍾

代碼中使用 WashingFactory 來封裝 4 種策略,使得策略沒有對外暴露,我們也了解到設計模式之間具有互補的關系,有些時候並不是單獨存在的。

代碼:
Strategy Pattern

總結

策略模式是一個很好的封裝各種復雜處理的設計模式,讓使用者根據自己的選擇來選中策略,而不用修改其他代碼。當策略太多的時候,可能造成使用方變得復雜、難管理多個策略的問題,利用工廠方法模式可以很好的解決這個難題。這其中也是一個見招拆招的問題,設計模式在真正運用中也是這樣子的,遇到問題使用恰當的設計模式去解決問題。

參考資料:《大話設計模式》、《設計模式之禪》

推薦閱讀:

公眾號之設計模式系列文章

希望文章對您有所幫助,設計模式系列會持續更新,感興趣的同學可以關注公眾號:LieBrother,第一時間獲取文章推送閱讀,也可以一起交流,交個朋友。

公眾號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM