1. 程式人生 > >Java 策略模式在專案中的實際運用

Java 策略模式在專案中的實際運用

       通常來說,策略模式是指對一系列的演算法定義,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化。

        策略模式的優點有:策略模式提供了管理相關的演算法族的辦法、策略模式提供了可以替換繼承關係的辦法、使用策略模式可以避免使用多重條件轉移語句。

        策略模式有三個部分組成:

                —抽象策略角色: 策略類,通常由一個介面或者抽象類實現。

                —具體策略角色:包裝了相關的演算法和行為。

                —環境角色:持有一個策略類的引用,最終給客戶端呼叫

        下面舉個策略模式在專案中實際應用的例子。在Java後臺專案中,一般都有將Excel表格匯入的需求,這裡必須想到在不同的模組中需要匯入的資料也是不同的,但是匯入需要的方法卻是通用的,比如都需要先匯出一個Excel表格作為資料寫入的模版,比如都需要匯出Excel表格中填寫不正確的資料等等。。。

1. 首先定義一個策略類,也就是下面的ExcelOperation 介面

public interface ExcelOperation {


    /**
     * 得到匯入資料的模板
     */
    void getExcelTemplate(String moduleName);


    /**
     * 預覽excel表格資料
     * @param excel
     * @return
     */
    Object previewExcelData(MultipartFile excel,String moduleName);


    /**
     * 匯出excel表格中格式錯誤資料
     */
    void exportExcelErrorData(String moduleName);


    /**
     * 匯入excel表格正確資料進入資料庫
     */
    Object importExcelCorrectData(String moduleName);

}

這裡每個函式都有一個引數為moduleName,這就是為了自動的根據你傳入的moduleName去呼叫相應模組的方法

2.具體的策略角色 也就是實現上述介面的類

@Service("lineExcel")
public class LineExcelImpl extends BaseExcel implements ExcelOperation{


    @Override
    public void getExcelTemplate(String moduleName) {
        String colName[] = { "線路名稱", "系統",  "規則模式","系統版本", "備註","描述" };
        try {
            generateImportExcel("lineExcelTemple",colName,true);
        } catch (IOException e) {
            logger.error("LineExcelImpl'getExcelTemplate has error",e);
        }
    }


    @Override
    public Object previewExcelData(MultipartFile excel, String moduleName) {
        ........
    }


    @Override
    public void exportExcelErrorData(String moduleName) {
       ........
    }


    @Override
    public Object importExcelCorrectData(String moduleName) {
    .......
    }

}

上述的策略實現類繼承了一個BaseExcel類 ,這只是一個封裝了一些匯入excel表格時需要用到的方法的工具類。這裡還用註解的方式將這個實現類放入了容器中。

3.環境角色,持有一個策略類的引用,最終給客戶端呼叫

@Component
public class ExcelOperationAdapter implements ExcelOperation,ApplicationContextAware {


    private  ApplicationContext appContext;


    private ExcelOperationAdapter(){}


    private ExcelOperation getExcelOperationImpl(String moduleName){
        return (ExcelOperation)appContext.getBean(moduleName);
    }


    @Override
    public void getExcelTemplate(String moduleName) {
        getExcelOperationImpl(moduleName).getExcelTemplate(moduleName);
    }


    @Override
    public Object previewExcelData(MultipartFile excel,String moduleName) {
        return getExcelOperationImpl(moduleName).previewExcelData(excel,moduleName);
    }


    @Override
    public void exportExcelErrorData(String moduleName) {
        getExcelOperationImpl(moduleName).exportExcelErrorData(moduleName);
    }


    @Override
    public Object importExcelCorrectData(String moduleName) {
        return getExcelOperationImpl(moduleName).importExcelCorrectData(moduleName);
    }




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

在這裡,我們的環境角色類除了實現了策略介面外,還實現了ApplicationContextAware 介面,實現這個介面的意義所在就是Spring容器會在建立該Bean之後,自動呼叫該Bean的setApplicationContextAware()方法,呼叫該方法時,會將容器本身作為引數傳給該方法——該方法中的實現部分將Spring傳入的引數(容器本身)賦給該類物件的appContext例項變數,因此接下來可以通過該appContext例項變數來訪問容器本身.

這樣的話,我們每實現一個策略實現類的時候,用宣告式註解將這個實現類注入到容器中,注意到我們的策略中每個方法都有一個moduleName引數,這個引數就是宣告式註解的名字。

4.在controler層呼叫實現類方法。

     @Autowired

    private ExcelOperationAdapter excelOperationAdapter;

    private static final String LINE_EXCEL_IMPL="lineExcel";

    excelOperationAdapter.getExcelTemplate(LINE_EXCEL_IMPL);

這就是一個完整的策略模式在應用中的實現了。多說一句,策略類的函式中的引數實際應用中一般都是物件,那麼我們只需要將策略實現類的註解名寫成物件某個欄位的固定值就可以了