1. 程式人生 > >你還在用if-else嗎?

你還在用if-else嗎?

作者:蝸蝸小小牛

連結:https://www.cnblogs.com/perryzjl/p/11097106.html

 

使用spring容器幹掉if-else

場景說明

最近新做一個專案,需要對不同店鋪的商品做不同處理。例如storeA需要進行handleA操作,storeB需要進行handleB操作,如此類推

大家很容易會想到下面的實現方法

 
public void handle(String storeName) { //店鋪A做操作handleA處理 if(storeName.equals("storeA")) { handleA(); } else if (storeName.equals("storeB")) { handleB(); //店鋪B做操作handleB處理 } else { //其他處理 } } 

確實上面的程式碼實現簡單易懂,但是如果店鋪越來越多,操作也越來越多的情況下,每新增一個店鋪都需要在這裡新增一次if else,大大的降低了程式碼的可維護性。

解決辦法

這個時候我們會希望可以各個店鋪的處理邏輯之間沒有關聯,互不影響。

抽象介面

我們所有的店鋪都會進行對應的操作,所以首先我們將方法抽象出來

 
public interface Store { void handle(); } 

根據不同店鋪做不同處理

 
@Service("storeA") public class StoreA implements Store { @Override void handle() { //handleA操作 } } @Service("storeB") public class StoreB implements Store { @Override void handle() { //handleB操作 } } 

添加工廠類

這樣還是有問題,因為還是要在業務程式碼中寫if-else來判斷到底是哪家store來進行操作,這個時候可以寫一個工廠類。

 
public class StoreFactory { @Autowired @Qualifier("storeA") private StoreA storeAA; @Autowired @Qualifier("storeB") private StoreB storeBB; //其他實現物件 public Store getStore(String storeName) { if (storeName.equals("storeA")) { return storeAA; } else if (storeName.equals("storeB")) { return storeBB; }//其他的條件下,返回其他的物件 } } 

添加工廠類後,我們在要獲取店鋪store時只需要呼叫getStore(String storeName)並傳入店鋪物件名即可,具體返回哪個物件,是storeA還是storeB,就交給工廠類來處理。

想免費學習Java工程化、分散式架構、高併發、高效能、深入淺出、微服務架構、SpringMyBatisNetty原始碼分析等技術的朋友,可以加群:834962734,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的視訊免費分享給大家,歡迎進群一起深入交流學習不管你是轉行,還是工作中想提升自己能力都可以

還是免不了寫if else,改造StoreFactory

在提供了工廠類之後,還是免不了寫很多的條件判斷,只不過是把所有的條件判斷寫在了一起。這時隨著產品數量的增多,if else 也會不停地增多,維護起來依然費勁。

這裡spring容器就可以派上用場了。spring中有一個BeanFactory物件,也是一個工廠,我們可以用它來改造StoreFactory。

 
public class StoreFactory { @Autowired private BeanFactory beanFactory; public Store getStore(String storeName) { Object bean = beanFactory.getBean(storeName); if (bean instanceof Store) { return (Store) bean; } throw new UnsupportedOperationException("不支援的店鋪:" + storeName); } } 

也可以利用Map自動裝配進行程式碼精簡

 
@Service public class StoreFactory { @Autowired Map<String, Store> stores = new ConcurrentHashMap<>(); //會在初始化的時候將所有的Store自動載入到Map中 public Store getStore(String store) { Store store = stores.get(store); if (store == null) { throw new RuntimeException("no store defined"); } return store; } } 

@Autowired的原始碼中有這樣一段註釋,大意就是@Autowired用於Collection或者Map型別時,容器會自動裝配所有已宣告的value型別的beans。

 
/* <p>In case of a {@link java.util.Collection} or {@link java.util.Map} dependency type, * the container autowires all beans matching the declared value type. For such purposes, * the map keys must be declared as type String which will be resolved to the corresponding * bean names. Such a container-provided collection will be ordered, taking into account * {@link org.springframework.core.Ordered}/{@link org.springframework.core.annotation.Order} * values of the target components, otherwise following their registration order in the * container. Alternatively, a single matching target bean may also be a generally typed * {@code Collection} or {@code Map} itself, getting injected as such. */ 

以上