23種設計模式——策略模式

一、策略模式

在策略模式(Strategy Pattern)中,一個類的行爲或其算法可以在運行時更改。這種類型的設計模式屬於行爲型模式。
在策略模式中,我們創建表示各種策略的對象和一個行爲隨着策略對象改變而改變的 context 對象。策略對象改變 context 對象的執行算法。

二、介紹

  • 意圖:定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。
  • 主要解決:在有多種算法相似的情況下,使用 if…else 所帶來的複雜和難以維護。
  • 何時使用:一個系統有許多許多類,而區分它們的只是他們直接的行爲。
  • 如何解決:將這些算法封裝成一個一個的類,任意地替換。
  • 關鍵代碼:實現同一個接口。
  • 應用實例:
    • 1、諸葛亮的錦囊妙計,每一個錦囊就是一個策略。
    • 2、旅行的出遊方式,選擇騎自行車、坐汽車,每一種旅行方式都是一個策略。
    • 3、JAVA AWT 中的 LayoutManager。
  • 優點:
    • 1、算法可以自由切換。
    • 2、避免使用多重條件判斷。
    • 3、擴展性良好。
  • 缺點:
    • 1、策略類會增多。
    • 2、所有策略類都需要對外暴露。
  • 使用場景:
    • 1、如果在一個系統裏面有許多類,它們之間的區別僅在於它們的行爲,那麼使用策略模式可以動態地讓一個對象在許多行爲中選擇一種行爲。
    • 2、一個系統需要動態地在幾種算法中選擇一種。
    • 3、如果一個對象有很多的行爲,如果不用恰當的模式,這些行爲就只好使用多重的條件選擇語句來實現。
  • 注意事項:如果一個系統的策略多於四個,就需要考慮使用混合模式,解決策略類膨脹的問題。

三、列表工具類

1、對兩個列表去重併合並。

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <code>Details determine success.</code>
 * by Liang ZC., Phd@Stanford
 *
 * @author LIANGZHICHENG
 * @date 2019-7-10 15:46
 * @see http://www.stanford.edu
 */
public class ListUtils {

    /**
     * {@param srcList} join {@param joinList} and the {@param srcList} will be distincted.
     *
     * @param srcList
     * @param joinList
     */
    public static <T> void joinAndDistinct(List<T> srcList,
                                           List<T> joinList) {

        if (CollectionUtils.isEmpty(srcList) && CollectionUtils.isEmpty(joinList)) {
            return;
        }

        LinkedHashSet tmpSet = Sets.newLinkedHashSet();

        tmpSet.addAll(srcList);

        if (CollectionUtils.isNotEmpty(joinList)) {
            tmpSet.addAll(joinList);
        }

        srcList.clear();
        srcList.addAll(tmpSet);
    }

    /**
     * Union two list and distinct .
     *
     * @param list1
     * @param list2
     * @param <T>
     * @return
     */
    public static <T> List<T> unionAndDistinct(List<T> list1,
                                               List<T> list2) {

        return org.apache.commons.collections4.ListUtils
                .union(list1, list2)
                .stream()
                .distinct()
                .collect(Collectors.toList());

    }

}

四、使用枚舉類實現策略模式

import com.google.common.collect.ImmutableMap;
import com.pingan.lcloud.ai.knowledgeBase.v2.common.ListUtils;
import com.pingan.lcloud.ai.knowledgeBase.v2.common.enums.FaqStepEnum;
import com.pingan.lcloud.ark.log.LoggerUtil;

import java.lang.annotation.Native;
import java.util.*;

/**
 * <code>Details determine success.</code>
 * by Liang ZC., Phd@Stanford
 *
 * @author LIANGZHICHENG
 * @date 2019-8-18 13:56
 * @see http://www.stanford.edu
 */
public enum StepEnum {
    /*
     *           N777777777NO
     *         N7777777777777N
     *        M777777777777777N
     *        *N877777777D77777M
     *       N M77777777ONND777M
     *       MN777777777NN  D777
     *     N7ZN777777777NN ~M7778
     *    N777777777777MMNN88777N
     *    N777777777777MNZZZ7777O
     *    DZN7777O77777777777777
     *     N7OONND7777777D77777N
     *      8*M++++?N???$77777$
     *       M7++++N+M77777777N
     *        N77O777777777777$                              M
     *          DNNM$$$$777777N                              D
     *         N*N:=N$777N7777M                             NZ
     *        77Z::::N777777777                          ODZZZ
     *       77N::::::N77777777M                         NNZZZ$
     *     $777:::::::77777777MN                        ZM8ZZZZZ
     *     777M::::::Z7777777Z77                        N++ZZZZNN
     *    7777M:::::M7777777$777M                       $++IZZZZM
     *   M777$:::::N777777*M7777M                       +++++ZZZDN
     *     NN$::::::7777$*M777777N                      N+++ZZZZNZ
     *       N::::::N:7*O:77777777                      N++++ZZZZN
     *       M::::::::::::N77777777+                   +?+++++ZZZM
     *       8::::::::::::D77777777M                    O+++++ZZ
     *        ::::::::::::M777777777N                      O+?D
     *        M:::::::::::M77777777778                     77=
     *        D=::::::::::N7777777777N                    777
     *       INN===::::::=77777777777N                  I777N
     *      ?777N========N7777777777787M               N7777
     *      77777*D======N77777777777N777N?         N777777
     *     I77777$$*N7===M$$77777777$77777777*MMZ77777777N
     *      $$$$$$$$$$*NIZN$$$$$$$$*M$$7777777777777777ON
     *       M$$$$$$$*M    M$$$$$$$*N=N$$$$7777777$$*ND
     *      O77Z$$$$$$$     M$$$$$$$*MNI==*DNNNNM=~N
     *   7 :N MNN$$$*M$      $$$777$8      8D8I
     *     NMM.:7O           777777778
     *                       7777777MN
     *                       M NO .7:
     *                       M   :   M
     *                            8
     */

    // Constant matcher factory methods

    ALL_STEP(0, "全部") {
        @Override
        public List<String> getUmList(List<String> umUsers,
                                      List<String> faqPrevRecorderUmUsers) {

            return ListUtils.unionAndDistinct(umUsers, faqPrevRecorderUmUsers);
        }
    },

    PEND_AUDIT_STEP(1, "待通過審覈") {
        @Override
        public List<String> getUmList(List<String> umUsers,
                                      List<String> faqPrevRecorderUmUsers) {

            return faqPrevRecorderUmUsers;
        }
    },

    AUDITING_STEP(2, "審覈中") {
        @Override
        public List<String> getUmList(List<String> umUsers,
                                      List<String> faqPrevRecorderUmUsers) {

            return faqPrevRecorderUmUsers;
        }
    },

    PASS_AUDIT_STEP(3, "已通過審覈") {
        @Override
        public List<String> getUmList(List<String> umUsers,
                                      List<String> faqPrevRecorderUmUsers) {

            return umUsers;
        }
    };

    /**
     * {@code STEP_MAP} include all step enum and isn`t change.
     */
    @Native private static final Map<Integer, StepEnum> STEP_MAP = ImmutableMap.of(
            ALL_STEP.getCode(), ALL_STEP,
            PEND_AUDIT_STEP.getCode(), PEND_AUDIT_STEP,
            AUDITING_STEP.getCode(), AUDITING_STEP,
            PASS_AUDIT_STEP.getCode(), PASS_AUDIT_STEP
    );

    private Integer code;

    private String value;

    /**
     * Return um information list
     *
     * @param umUsers
     * @param faqPrevRecorderUmUsers
     * @return
     */
    public abstract List<String> getUmList(List<String> umUsers,
                                           List<String> faqPrevRecorderUmUsers);

    StepEnum(Integer code,
             String value) {
        this.code = code;
        this.value = value;
    }

    public Integer getCode() {
        return code;
    }

    public String getValue() {
        return value;
    }

    /**
     * Return um information list by {@param step} , and the {@param step} must in {@link FaqStepEnum}.
     *
     * @param umUsers
     * @param faqPrevRecorderUmUsers
     * @param step
     * @return
     */
    public static List<String> getUmListByStep(List<String> umUsers,
                                               List<String> faqPrevRecorderUmUsers,
                                               Integer step) {

        if (Objects.isNull(step)) {
            LoggerUtil.warn("step is null.");
            return Collections.emptyList();
        }

        return STEP_MAP.get(step).getUmList(umUsers, faqPrevRecorderUmUsers);
    }

    public static void main(String[] args) {
        
        List<String> a = Arrays.asList("a");
        List<String> b = Arrays.asList("b");
        Integer step = 1;
        System.out.println(StepEnum.AUDITING_STEP.getUmList(a, b));
        System.out.println(StepEnum.ALL_STEP.getUmList(a, b));
        System.out.println(StepEnum.PEND_AUDIT_STEP.getUmList(a, b));
        System.out.println(StepEnum.PASS_AUDIT_STEP.getUmList(a, b));
        System.out.println(StepEnum.getUmListByStep(a, b, step));

    }
}

四、輸出結果

[b]
[a, b]
[b]
[a]
[b]

關注我的技術公衆號《漫談人工智能》,每天推送優質文章

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