1. 程式人生 > >java設計模式——策略模式

java設計模式——策略模式

pri 新增 業務場景 map ace 的區別 提高 安全性 scrip

一. 定義與類型

定義:針對一組算法,將每一種算法都封裝到具有共同接口的獨立的類中,從而是它們可以相互替換。策略模式的最大特點是使得算法可以在不影響客戶端的情況下發生變化,從而改變不同的功能。當代碼中有大量的if...else...時,可以使用策略模式

類型:行為型。

二. 使用場景

(1) 系統有很多類,而他們的區別僅僅在於他們的行為不同

(2) 一個系統需要動態的幾種算法中選擇一種

三. 優缺點

優點:

  (1) 符合開閉原則

  (2) 避免使用多重條件轉移語句

  (3) 提高算法的保密性和安全性

缺點:

  (1) 客戶端必須知道所有的策略類,並自行決定使用哪一個策略類

  (2) 產生很多策略類

四. 相關設計模式

策略模式和工廠模式

  

策略模式和狀態模式

五. Coding

先引入一個業務場景:假設在618和雙十一的時候,各大電商會有各種促銷;而促銷就是課程的一個行為,但是這種促銷行為有多種實現,網站裏面的課程促銷:

先創建一個促銷策略接口:

/**
 * @program: designModel
 * @description: 促銷策略接口
 * @author: YuKai Fan
 * @create: 2019-02-13 16:47
 **/
public interface PromotionStrategy {
    void doPromotion();
}

創建三個實現類分別代表各種策略,實現策略接口,立減策略:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2019-02-13 16:48
 **/
public class LiJianPromotionStrategy implements PromotionStrategy {
    public void doPromotion() {
        System.out.println("立減促銷,課程的價格直接減去配置的價格");
    }
}

返現策略:

/**
 * @program: designModel
 * @description:
 * 
@author: YuKai Fan * @create: 2019-02-13 16:50 **/ public class FanXianPromotionStrategy implements PromotionStrategy { public void doPromotion() { System.out.println("返現促銷,返回的金額存放到網站用戶的余額中"); } }

滿減策略:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2019-02-13 16:49
 **/
public class ManJianPromotionStrategy implements PromotionStrategy {
    public void doPromotion() {
        System.out.println("滿減促銷,滿200減20元");
    }
}

策略執行類:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2019-02-13 16:51
 **/
public class PromotionActivity {

    private PromotionStrategy promotionStrategy;

    public PromotionActivity(PromotionStrategy promotionStrategy) {
        this.promotionStrategy = promotionStrategy;
    }

    public void executePromotionStrategy() {
        promotionStrategy.doPromotion();
    }
}

應用層:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2019-02-13 16:52
 **/
public class Test {
    public static void main(String[] args) {
        //在618的時候,使用立減策略
        PromotionActivity promotionActivity618 = new PromotionActivity(new LiJianPromotionStrategy());
        //在雙11的時候,使用滿減策略
        PromotionActivity promotionActivity1111 = new PromotionActivity(new ManJianPromotionStrategy());

        promotionActivity618.executePromotionStrategy();
        promotionActivity1111.executePromotionStrategy();

    }
}

結果:

技術分享圖片

UML類圖:

技術分享圖片

如果要修改業務,只需要新增一個策略類即可,還可以對上面的應用層進行改進

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2019-02-13 16:52
 **/
public class Test {
    public static void main(String[] args) {

        PromotionActivity promotionActivity = null;

        //創建一個promotionKey
        String promotionKey = "LIJIAN";
        if (StringUtils.equals(promotionKey, "LIJIAN")) {
            promotionActivity = new PromotionActivity(new LiJianPromotionStrategy());
        } else if (StringUtils.equals(promotionKey, "FANXIAN")) {
            promotionActivity = new PromotionActivity(new FanXianPromotionStrategy());
        }//....

        promotionActivity.executePromotionStrategy();

}

結果:

技術分享圖片

還可以把策略模式和工廠模式結合到一起(為了避免空指針異常,可以創建一個空的促銷策略):

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2019-02-13 17:10
 **/
public class EmptyPromotionStrategy implements PromotionStrategy {
    public void doPromotion() {
        System.out.println("無促銷");
    }
}

創建一個促銷策略工廠類:

/**
 * @program: designModel
 * @description: 促銷策略工廠的實現
 * @author: YuKai Fan
 * @create: 2019-02-13 17:10
 **/
public class PromotionStrategyFactory {
    private static Map<String, PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<String, PromotionStrategy>();
    static {
        PROMOTION_STRATEGY_MAP.put(PromotionKey.LIJIAN, new LiJianPromotionStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.FANXIAN, new FanXianPromotionStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.MANJIAN, new ManJianPromotionStrategy());
    }

    private static final PromotionStrategy NON_PROMOTION = new EmptyPromotionStrategy();

    private PromotionStrategyFactory() {

    }

    public static PromotionStrategy getNonPromotion(String promotionKey) {
        PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
        return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
    }

    private interface PromotionKey{
        String LIJIAN = "LIJIAN";
        String FANXIAN = "FANXIAN";
        String MANJIAN = "MANJIAN";
    }
}

應用層:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2019-02-13 16:52
 **/
public class Test {
    public static void main(String[] args) {

        /**
         * 策略模式與工廠模式結合
         */
        String promotionKey = "LIJIAN";

        PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.getNonPromotion(promotionKey));
        promotionActivity.executePromotionStrategy();

    }
}

結果:

技術分享圖片

策略模式一般都不會單獨去使用,一般會結合單例,工廠方法,享元模式去使用

六. 源碼分析

java設計模式——策略模式