結合Spring特性實現策略模式


今天我們來了解下設計模式中比較常用的策略模式

什么是策略模式?

策略模式定義了一系列的算法,並將每一個算法封裝起來,使每個算法可以相互替代,使算法本身和使用算法的客戶端分割開來,相互獨立。(摘自百度)

策略模式適用於什么場景?

一個大功能,它有許多不同類型的實現(策略類),具體根據客戶端來決定采用特定的策略類。
比如下單、物流對接、網關的加簽驗簽等。

以物流對接為例來比較簡單工廠模式和策略模式。

具體業務為每個物流公司都有它們對應的code,加簽方法,物流查詢方法

首先我們定義好接口類

public interface Logistics {

    /**
     * 物流公司唯一標識
     * @return
     */
    String companyCode();

    /**
     * 加簽
     * @param request
     */
    String sign(SignRequest request);

    /**
     * 查詢物流信息
     */
    LogisticsInfoResponse queryLogisticsInfo(QueryLogisticsInfoRequest request);

}

對接順風和圓通

@service("shunfengLogistics")
public class ShunfengLogistics implements Logistics {

    @Override
    public String companyCode() {
        return "shunfeng";
    }

    @Override
    public String sign(SignRequest request) {
        //do your biz
        
        return null;
    }

    @Override
    public LogisticsInfoResponse queryLogisticsInfo(QueryLogisticsInfoRequest request) {
        //do your biz
        
        return null;
    }
}

@service("yuantongLogistics")
public class YuantongLogistics implements Logistics {

    @Override
    public String companyCode() {
        return "yuantong";
    }

    @Override
    public String sign(SignRequest request) {
        //do your biz
        
        return null;
    }

    @Override
    public LogisticsInfoResponse queryLogisticsInfo(QueryLogisticsInfoRequest request) {
        //do your biz
        
        return null;
    }
}

簡單工廠模式

public class LogisticsFactory {

    @Autowired
    private Logistics shunfengLogistics;

    @Autowired
    private Logistics yuantongLogistics;

    public Logistics getLogistics(LogisticsRequest request) {

        String company = request.getCompanyCode();

        if ("shunfeng".equals(company)) {
        
            return shunfengLogistics;
        }

        if ("yuantong".equals(company)) {
       
            return yuantongLogistics;
        }
        
        throw new BizException("物流公司類型錯誤");
    }
}

每當我們接入一家物流公司的時候都要使LogisticsFactory加一段if分支。這就違反了設計模式的開閉原則

策略模式結合Spring特性

其實不結合Spring特性的話,策略模式還是有上述問題存在。
我們先來准備下spring相關知識

1.實現InitializingBean接口。相信這個大家並不陌生。就是spring容器創建bean的時候幫你執行初始化的接口

2.實現ApplicationContextAware接口。通俗的講,實現了這個接口的bean相當於是拿到了ApplicationContext,相當於整個spring容器的資源。

3.ApplicationContext接口的getBeansOfType方法。獲取整個spring容器中某個類型的bean,返回的是map類型。key對應beanName, value對應bean。

@Component
public class LogisticsResolver implements InitializingBean, ApplicationContextAware {

    private ApplicationContext applicationContext;

    private Map<String, Sign> logisticsHandlerMap = new HashMap<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() {
        Map<String, Sign> beanMap = applicationContext.getBeansOfType(Logistics.class);
        for (String key : beanMap.keySet()) {
            this.logisticsHandlerMap.put(beanMap.get(key).companyCode(), beanMap.get(key));
        }
    }

    public Logistics getHandler(String companyCode) {
        return logisticsHandlerMap.get(companyCode);
    }

}

通過spring容器去獲取對應的所有實現類,並組裝成我們想要的companyCode→bean的map。通過getHandler方法就能拿到對應的實現類。

但是現在我們每次加一個策略類的時候都交由Spring去管理,只管加就行了


免責聲明!

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



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