秒懂設計模式之策略模式(Strategy Pattern)

版權申明】非商業目的可自由轉載
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/88085445
出自:shusheng007

設計模式系列文章:
秒懂Java代理與動態代理模式
秒懂設計模式之建造者模式(Builder Pattern)
秒懂設計模式之工廠方法模式(Factory Method Pattern)
秒懂設計模式之抽象工廠模式(Abstract Factory Pattern)

前言

人在IT江湖飄,不懂設計模式咋裝X?

我們這個社會上的事情大概率都符合八二法則,軟件領域也一樣。例如你學習一門編程語言,工作中常用的類來來回回也就那麼幾十個。那麼多設計模式,最常被人使用的也就那麼幾種,所以我們在做事情的時候應該首先着眼於那20%。

策略模式算是設計模式中簡單而又常用的了。

定義

策略模式定義了一系列的算法,並將每一個算法封裝起來,使他們可以相互替換。

使用場景

當你寫代碼的時候發現一個操作有好多種實現方法,而你需要根據不同的情況使用if-else等分支結構來確定使用哪種實現方式的時候,想一想這個模式。

如何實現

業務場景

2017年的2月14號,王二狗和牛翠花約好在天津之眼約定終身,二狗打扮一番後準備出發,此時問題來了:是坐公交去呢,還是打滴滴快車呢?天氣看起來也不錯,要不騎共享單車吧,省錢還鍛鍊身體。

對應到編程領域就是:目前有三種策略可以實現一個特定的目的,使用何種策略取決於調用者(客戶端)

普通實現

如果我們正常寫代碼,平時也應該這樣,首先保證把功能正確的實現了,然後慢慢重構,設計模式都是在不斷的重構當中應用的。 王二狗會調用會調用goToTianJinEye()方法,根據自己的實際情況,選擇某一種出行方式。

public class TrafficFeeCalculator {
    public int goToTianJinEye(String way, int distance) {
        int trafficFee = 0;
        switch (way) {
            case "bus":
                if (distance < 10)
                    trafficFee = 4;
                else
                    trafficFee = 6;
                break;
            case "didi":
                if(distance<3)
                    trafficFee = 8;
                else 
                    trafficFee=8+(distance-3)*3;
                break;
            case "sharedBicyle":
                trafficFee = 2;
                break;
            default:
                break;
        }
        return trafficFee;
    }
}

那麼這麼寫有什麼弊端呢?
第一:每一種出行方式的交通花費的計算方式都寫在了TrafficFeeCalculator類中,這個類承擔的職責較多,違反了單一職責原則。
第二:假如王二狗突然想自己開車去,那就需要修改goToTianJinEye這個方法了。違反了開閉原則。

使用策略模式

以上的場景非常適合使用策略模式,將多種不同的實現算法封裝,然後客戶端根據不同策略分別調用相應的算法。
在這裏插入圖片描述

第一步:封裝不同的實現算法
首先定義一個策略接口,規定算法的同一操作

public interface CalculateStrategy {
    int calculateTrafficFee(int distance);
}

第二步:封裝各個算法

//乘坐公交車算法
public class ByBus implements CalculateStrategy {
    @Override
    public int calculateTrafficFee(int distance) {
        return distance<10?4:6;
    }
}
//乘坐滴滴快車算法
public class ByDiDiExpress implements CalculateStrategy {
    @Override
    public int calculateTrafficFee(int distance) {
        return distance<3?8:(8+(distance-3)*3);
    }
}
//騎共享單車算法
public class BySharedBicycle implements CalculateStrategy {
    @Override
    public int calculateTrafficFee(int distance) {
        return 2;
    }
}

第三步:使用算法

public class TrafficFeeCalculator {
...

    public int goToTianJinEye(CalculateStrategy strategy,int distance){
        return strategy.calculateTrafficFee(distance);
    }
}

第四步:客戶端調用
根據情況,構建相應的算法類實例,傳入計算器計算即可

    public static void main(String[] args) {
        TrafficFeeCalculator calculator=new TrafficFeeCalculator();
        System.out.println(String.format("乘坐公交車到天津之眼的花費爲:%d塊人民幣",
                calculator.goToTianJinEye(new ByBus(),10)));
        System.out.println(String.format("乘坐滴滴快車到天津之眼的花費爲:%d塊人民幣",
                calculator.goToTianJinEye(new ByDiDiExpress(),10)));
        System.out.println(String.format("騎共享單車到天津之眼的花費爲:%d塊人民幣",
                calculator.goToTianJinEye(new BySharedBicycle(),10)));
    }

輸出爲:

乘坐公交車到天津之眼的花費爲:6塊人民幣
乘坐滴滴快車到天津之眼的花費爲:29塊人民幣
騎共享單車到天津之眼的花費爲:2塊人民幣

二狗爲了早點見到自己心愛的牛翠花,最終選擇了滴滴快車,貴是貴了點,但是快!

優缺點

優點:降低了算法類的職責,使各個算法可以獨立變化並互相替換。而且使得增加新的算法變的很容易,降低了對原有系統的侵入,最終使得程序可擴展可維護性增強。

缺點:所有設計模式的通病,類增多了,程序從局部來看變的更復雜了。

總結

是不是感覺講設計模式的文章都有一個特點,使用了設計模式反而比不使用設計模式使程序看起來更加複雜,而不是更加簡單。那是因爲每篇文章的示例都是無實際使用意義的示例代碼,實際情況是程序非常複雜才需要使用到設計模式。一個大型程序是不斷迭代出來的,一開始肯定不長那樣,程序員日常接到一個開發任務也不要過多的想,這個我應該用個什麼設計模式呀?先把功能實現了,然後回頭看看有沒有遵循面向對象編程6大原則,如果沒有想想怎麼改進,然後設計模式就登場了。。。

設計模式值得你刻意練習!

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