spring容器幹掉if-else

場景說明

最近新作一個項目,須要對不一樣店鋪的商品作不一樣處理。例如storeA須要進行handleA操做,storeB須要進行handleB操做,如此類推php

你們很容易會想到下面的實現方法java

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

確實上面的代碼實現簡單易懂,可是若是店鋪愈來愈多,操做也愈來愈多的狀況下,每新增一個店鋪都須要在這裏添加一次if else,大大的下降了代碼的可維護性。spring

解決辦法

這個時候咱們會但願能夠各個店鋪的處理邏輯之間沒有關聯,互不影響。less

抽象接口

咱們全部的店鋪都會進行對應的操做,因此首先咱們將方法抽象出來ide

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來進行操做,這個時候能夠寫一個工廠類。ui

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,就交給工廠類來處理。spa

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

在提供了工廠類以後,仍是免不了寫不少的條件判斷,只不過是把全部的條件判斷寫在了一塊兒。這時隨着產品數量的增多,if else 也會不停地增多,維護起來依然費勁。
這裏spring容器就能夠派上用場了。spring中有一個BeanFactory對象,也是一個工廠,咱們能夠用它來改造StoreFactory。code

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。component

/* <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. */
相關文章
相關標籤/搜索