策略模式:定義了演算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化獨立於使用演算法的客戶。
傳統的策略模式一般是建立公共介面、定義公共方法——》然後建立實體類實現公共介面、根據各自的邏輯重寫公共方法——》建立一個行為隨著策略物件改變而改變的 context 物件——》根據不同的傳參,呼叫不同的介面實現類方法,達到只改變引數即可獲得不同結果的目的。
但是也可以明顯發現,這種策略模式的實現方式,程式碼量較大,而且還要自定義要傳遞的引數,可能會引入一定數量的if/else,有一定的優化空間,接下來,我會結合實際開發經驗,分享一種策略模式的優化方式,進一步優化程式碼結構、減少程式碼量。
首先,必不可少的需要建立公共介面、定義公共方法,然後建立實體類實現公共介面、根據各自的邏輯重寫公共方法,參考程式碼如下:
定義公共介面CommonService,以及公共方法push()
1 package com.itcq.service.StrategyPattern; 2 3 public interface CommonService { 4 String push(String key); 5 }
建立三個不同的介面實現類,重寫push()方法
1 package com.itcq.service.StrategyPattern; 2 import org.springframework.stereotype.Service; 3 4 @Service 5 public class TestOne implements CommonService { 6 @Override 7 public String push(String key) { 8 return "1.這是模式:" + key; 9 } 10 }
1 package com.itcq.service.StrategyPattern; 2 3 import org.springframework.stereotype.Service; 4 5 @Service 6 public class TestTwo implements CommonService{ 7 @Override 8 public String push(String key) { 9 return "2.這是模式:"+key; 10 } 11 }
1 package com.itcq.service.StrategyPattern; 2 import org.springframework.stereotype.Service; 3 4 @Service 5 public class TestThree implements CommonService{ 6 @Override 7 public String push(String key) { 8 return "3.這是模式:"+key; 9 } 10 }
接下來就是重點,我們利用到springboot初始化Bean的方式結合HashMap,來實現對策略模式的優化
1 @Service 2 public class TestServiceTwo implements InitializingBean { 3 4 @Autowired 5 private ApplicationContext applicationContext; 6 7 private HashMap<String, CommonService> hashmap = new HashMap<>(); 8 9 @Override 10 public void afterPropertiesSet() { 11 12 hashmap.put(StrategyTestEnum.STRATEGY_ONE.getTitle(), new TestOne()); 13 hashmap.put(StrategyTestEnum.STRATEGY_TWO.getTitle(), this.applicationContext.getBean(TestTwo.class)); 14 hashmap.put(StrategyTestEnum.STRATEGY_THREE.getTitle(), this.applicationContext.getBean(TestThree.class)); 15 } 16 }
1 @Getter 2 public enum StrategyTestEnum { 3 STRATEGY_ONE("一", "模式一"), 4 STRATEGY_TWO("二", "模式二"), 5 STRATEGY_THREE("三", "模式三"), 6 ; 7 8 private String title; 9 private String value; 10 11 StrategyTestEnum(String title, String value) { 12 this.title = title; 13 this.value = value; 14 } 15 }
TestServiceTwo實現InitializingBean介面,InitializingBean介面為bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是繼承該介面的類,在初始化bean的時候都會執行該方法。
定義一個hashmap集合,用來儲存不同的公共介面實現類物件,這裡把引數抽取成一個列舉類,利用SpringBoot的高階容器ApplicationContext,獲取Bean物件,當然這裡直接new一個實現類物件也是可以的,將不同的引數和實現物件封裝到map集合中,實現引數和邏輯一一對應。
測試方法如下,通過hashmap的key獲取對應的實現類物件,這樣就不必再自定義引數型別,徹底消除了if/else,也不用暴露給方法呼叫者過多的業務邏輯。
1 public String testMethod2(String key) { 2 3 CommonService commonService = hashmap.get(key); 4 Assert.notNull(commonService, "引數錯誤,找不到模式"); 5 return commonService.push(key); 6 }
最後在controller層呼叫方法,進行測試:
1 @Autowired 2 private TestServiceTwo testServiceTwo; 3 4 @GetMapping("/test/two") 5 public String testMethodTwo(@RequestParam(name = "key") String key) { 6 7 return testServiceTwo.testMethod2(key); 8 }
測試結果如下:
引數正確情況下:
引數錯誤情況下:
利用這種自定義初始化bean+hashmap的方式完成了對策略模式的優化,優化了程式碼的結構,並且徹底消除了if/else,個人認為可以很好地提升程式碼質量。