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); |