天天看點

flea-frame-common使用之通用政策模式實作通用政策模式實作 — Flea Strategy

通用政策模式實作 — Flea Strategy

1. 概述

政策模式(Strategy Pattern)作為一種軟體設計模式,用來實作對象的某個行為,該行為在不同的場景中擁有不同的實作邏輯。它定義了一組算法,同時将這些算法封裝起來,并使它們之間可以互換。

常用的政策模式有如下三個角色:

  • 抽象政策角色 — Strategy

    抽象政策類,通常為一個接口,其中定義了某個政策行為【即政策算法辨別】。

  • 具體政策角色 — ConcreteStrategy

    具體政策類,實作抽象政策中的政策行為;每一個具體政策類即代表一種政策算法。

  • 上下文角色 — Context

    上下文類,起承上啟下封裝作用,屏蔽高層子產品對政策、算法的直接通路,封裝可能存在的變化。

本篇在上述常用的政策模式基礎上,結合門面模式和調整後的政策上下文,建構了一套通用政策模式實作。

下面我們這套通用政策模式來模拟一下各種動物的喊叫行為:

flea-frame-common使用之通用政策模式實作通用政策模式實作 — Flea Strategy

2. 參考

flea-frame-common使用之通用政策模式實作 源代碼

3. 實作

3.1 定義Flea政策接口類 — IFleaStrategy

該類定義了通用的政策行為,T 類型表示 Flea 政策執行結果對應的類型,P 類型表示 Flea 政策上下文參數。 具體代碼如下:

/**
 * Flea政策接口,定義統一的政策執行方法。
 *
 * @param <T> Flea政策執行結果對應的類型
 * @param <P> Flea政策上下文參數
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public interface IFleaStrategy<T, P> {

    /**
     * 政策執行
     *
     * @param contextParam Flea政策上下文參數
     * @return 政策執行結果對應的類型
     * @throws FleaStrategyException Flea政策異常
     * @since 1.1.0
     */
    T execute(final P contextParam) throws FleaStrategyException;
}
           

3.2 定義狗叫喊聲政策類 — DogVoiceStrategy

/**
 * 狗喊叫聲政策
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class DogVoiceStrategy implements IFleaStrategy<String, String> {

    @Override
    public String execute(String name) throws FleaStrategyException {
        return "阿狗【" + name + "】正在叫喊着;汪汪汪";
    }

}
           

3.3 定義貓叫喊聲政策類 — CatVoiceStrategy

/**
 * 貓喊叫聲政策
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class CatVoiceStrategy implements IFleaStrategy<String, String> {

    @Override
    public String execute(String name) throws FleaStrategyException {
        return "阿貓【" + name + "】正在叫喊着;喵喵喵";
    }

}
           

3.4 定義鴨叫喊聲政策類 — DuckVoiceStrategy

/**
 * 鴨喊叫聲政策
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class DuckVoiceStrategy implements IFleaStrategy<String, String> {

    @Override
    public String execute(String name) throws FleaStrategyException {
        return "阿鴨【" + name + "】正在叫喊着;嘎嘎嘎";
    }

}
           

3.5 定義政策上下文接口類 — IFleaStrategyContext

政策上下文接口,定義統一的政策上下文調用方法,同時可通過 getContext 擷取上下文參數,setContext 設定上下文參數。

/**
 * Flea政策上下文接口,定義統一的政策上下文調用方法。
 *
 * @param <T> Flea政策執行結果對應的類型
 * @param <P> Flea政策上下文參數
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public interface IFleaStrategyContext<T, P> {

    /**
     * 政策上下文調用
     *
     * @param strategy 政策名稱
     * @return 政策執行結果對應的類型
     * @throws FleaStrategyException Flea政策異常
     * @since 1.1.0
     */
    T invoke(String strategy) throws FleaStrategyException;

    /**
     * 設定政策上下文參數
     *
     * @param contextParam 上下文參數對象
     * @since 1.1.0
     */
    void setContext(P contextParam);

    /**
     * 擷取政策上下文參數
     *
     * @return 政策上下文參數
     * @since 1.1.0
     */
    P getContext();
}
           

3.6 定義Flea抽象政策上下文類 — FleaStrategyContext

Flea 抽象政策上下文類,封裝了政策執行的邏輯,對外屏蔽高層子產品對政策的直接通路。抽象方法 init 用于初始化 Flea 政策實作 Map,該方法由Flea 政策抽象上下文的子類實作,并在政策上下文子類執行個體化時,調用該方法完成具體初始化的工作。

/**
 * Flea抽象政策上下文,封裝了公共的政策執行邏輯,
 * 其中Flea政策Map由其子類進行初始化,鍵為政策名,
 * 值為具體的Flea政策執行個體。
 *
 * @param <T> Flea政策執行結果對應的類型
 * @param <P> Flea政策上下文參數
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public abstract class FleaStrategyContext<T, P> implements IFleaStrategyContext<T, P> {

    private Map<String, IFleaStrategy<T, P>> fleaStrategyMap; // Flea政策Map

    private P contextParam; // Flea政策上下文參數

    /**
     * 初始化政策上下文
     *
     * @since 1.1.0
     */
    public FleaStrategyContext() {
        fleaStrategyMap = init();
    }

    /**
     * 初始化政策上下文
     *
     * @param contextParam Flea政策上下文參數
     * @since 1.1.0
     */
    public FleaStrategyContext(P contextParam) {
        this();
        this.contextParam = contextParam;
    }

    /**
     * 初始化Flea政策Map
     *
     * @return Flea政策Map
     * @since 1.1.0
     */
    protected abstract Map<String, IFleaStrategy<T, P>> init();

    @Override
    public T invoke(String strategy) throws FleaStrategyException {
        if (ObjectUtils.isEmpty(fleaStrategyMap)) {
            throw new FleaStrategyException("The Strategy Map is not initialized!");
        }
        IFleaStrategy<T, P> fleaStrategy = fleaStrategyMap.get(strategy);
        if (ObjectUtils.isEmpty(fleaStrategy)) {
            throw new FleaStrategyNotFoundException("The Strategy [name =\"" + strategy + "\"] is not found!");
        }
        return fleaStrategy.execute(contextParam);
    }

    @Override
    public void setContext(P contextParam) {
        this.contextParam = contextParam;
    }

    @Override
    public P getContext() {
        return contextParam;
    }
}
           

3.7 定義動物叫喊聲政策上下文類 — AnimalVoiceContext

動物叫喊聲政策上下文,繼承 Flea 抽象政策上下文,實作 init 方法,用于初始化 Flea 政策實作 Map,其中 key 為 政策名,value 為 具體的動物叫喊聲政策實作類;Collections.unmodifiableMap 用于傳回一個 隻讀 的 Map。

/**
 * 動物叫喊聲政策上下文
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class AnimalVoiceContext extends FleaStrategyContext<String, String> {

    public AnimalVoiceContext() {
    }

    public AnimalVoiceContext(String contextParam) {
        super(contextParam);
    }

    @Override
    protected Map<String, IFleaStrategy<String, String>> init() {
        Map<String, IFleaStrategy<String, String>> fleaStrategyMap = new HashMap<>();
        fleaStrategyMap.put("dog", new DogVoiceStrategy());
        fleaStrategyMap.put("cat", new CatVoiceStrategy());
        fleaStrategyMap.put("duck", new DuckVoiceStrategy());
        return Collections.unmodifiableMap(fleaStrategyMap);
    }

}
           

3.8 定義Flea政策門面 — FleaStrategyFacade

/**
 * Flea政策門面,定義政策調用的統一入口。
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class FleaStrategyFacade {

    private FleaStrategyFacade() {
    }

    /**
     * 政策門面調用方法
     *
     * @param strategy            政策名
     * @param fleaStrategyContext 政策上下文
     * @param <T>                 Flea政策執行結果對應的類型
     * @param <P>                 Flea政策上下文參數
     * @return Flea政策執行結果對應的類型
     * @throws FleaStrategyException Flea政策異常
     * @since 1.1.0
     */
    public static <T, P> T invoke(String strategy, IFleaStrategyContext<T, P> fleaStrategyContext) throws FleaStrategyException {
        return fleaStrategyContext.invoke(strategy);
    }
}
           

4. 測試

單元自測類可檢視 FleaStrategyTest。

/**
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class FleaStrategyTest {

    private static final FleaLogger LOGGER = FleaLoggerProxy.getProxyInstance(FleaStrategyTest.class);

    @Test
    public void testStrategy() {

        AnimalVoiceContext context = new AnimalVoiceContext("旺财");
        LOGGER.debug(FleaStrategyFacade.invoke("dog", context));

        context.setContext("Tom");
        LOGGER.debug(FleaStrategyFacade.invoke("cat", context));

        context.setContext("Donald");
        LOGGER.debug(FleaStrategyFacade.invoke("duck", context));

    }
}

           

單元測試類運作結果如下:

flea-frame-common使用之通用政策模式實作通用政策模式實作 — Flea Strategy

繼續閱讀