使用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,就交給工廠類來處理。
還是免不了寫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.
*/
最後
以上就是全部內容。
歡迎轉載,轉載請說明出處:https://www.cnblogs.com/perryzjl/p/11097106.html