欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何優(yōu)雅的替換掉Java代碼中的if else

 更新時間:2020年09月08日 11:43:47   作者:崔笑顏  
這篇文章主要介紹了如何優(yōu)雅的替換掉Java代碼中的if else,幫助大家優(yōu)化自己的Java代碼,提高可讀性與簡潔性,感興趣的朋友可以了解下

場景

平時我們在寫代碼時,需要針對不同情況處理不同的業(yè)務(wù)邏輯,用得最多的就是if和else。 但是如果情況太多,就會出現(xiàn)一大堆的“if else”,這就是為什么很多遺留系統(tǒng)中,一個函數(shù)可能出現(xiàn)上千行的代碼。當然你說可以通過抽取方法或者類來實現(xiàn),每一個情況交給一個方法或者對應(yīng)一個類來處理,但是這樣做只是看起來代碼整潔了一些,還是有大量的”if else",后面有新的邏輯時,又要添加更多的“if else",沒有從根本上解決問題。

舉個例子,短信發(fā)送業(yè)務(wù)的實現(xiàn),一般公司會接入多個短信供應(yīng)商,比如夢網(wǎng)、玄武、阿里云等多個短信平臺(我們稱之為短信渠道),可能需要針對不同的短信類型或者短信平臺的穩(wěn)定性來切換短信渠道:

比如阿里云短信管控很嚴,帶營銷字樣的短信不讓發(fā)送,則營銷類短信需要使用其他短信渠道來發(fā)送;
也有可能某個短信平臺服務(wù)掛了暫時不可用,需要切換到另一個短信渠道;
某些短信平臺有優(yōu)惠,則需要臨時切換到該短信渠道發(fā)送短信;

代碼實現(xiàn)

上面的業(yè)務(wù)場景簡單來說就是:針對不同的短信渠道來調(diào)用對應(yīng)的短信平臺接口實現(xiàn)短信發(fā)送。
短信渠道一般配置在文件中,或者配置在數(shù)據(jù)庫中。

代碼實現(xiàn)如下(注意下面所有的代碼都不能直接運行,只是關(guān)鍵邏輯部分的示例代碼):

爛代碼示例

我們有一個短信發(fā)送類:SmsSendService,里面有一個send方法發(fā)送短信

SmsSendService.java

public class SmsSendService{
	/**
 	 * @Param phoneNo 手機號
	 * @Param content 短信內(nèi)容
	 */
	public void send(String phoneNo,String content){
		//從配置中讀取 短信渠道
		String channelType=config.getChannelType();
		
		//如果是短信渠道A,則調(diào)用渠道A的api發(fā)送
		if(Objects.equals(channelType,"CHANNEL_A")){
			System.out.println("通過短信渠道A發(fā)送短信");
		}
		//如果是短信渠道B,則調(diào)用渠道B的api發(fā)送
		else if(Objects.equals(channelType,"CHANNEL_B")){
			System.out.println("通過短信渠道B發(fā)送短信");
		}
	}
}

如果某天增加了一個短信渠道C,那么接著追加一個”else if…"

//... 此處省略部分代碼 ...

//從配置中讀取 短信渠道
String channelType=config.getChannelType();
//如果是短信渠道A,則調(diào)用渠道A的api發(fā)送
if(Objects.equals(channelType,"CHANNEL_A")){
	System.out.println("通過短信渠道A發(fā)送短信");
}
//如果是短信渠道B,則調(diào)用渠道B的api發(fā)送
else if(Objects.equals(channelType,"CHANNEL_B")){
	System.out.println("通過短信渠道B發(fā)送短信");
}
//ADD: 如果是短信渠道C,則調(diào)用渠道C的api發(fā)送
else if(Objects.equals(channelType,"CHANNEL_C")){
	System.out.println("通過短信渠道C發(fā)送短信");
}

//... 此處省略部分代碼 ...

如果又加其他短信渠道了呢?你又寫一個“else if …" ?
顯然這種做法不可取,也不符合SOLID原則中的”開閉原則“ ——對擴展開放,對更改封閉。
這樣我們每次都需要修改原有代碼(對更改沒有封閉),不斷的添加”if else"。
接下來我們把代碼優(yōu)化一下:

優(yōu)化代碼1

定義一個短信渠道的接口 SmsChannelService,所有的短信渠道API都實現(xiàn)該接口;

短信渠道接口 SmsChannelService.java

public interface SmsChannelService{
	//發(fā)送短信
	void send(String phoneNo,String content);
}

短信渠道A SmsChannelServiceImplA.java

public class SmsChannelServiceImplA implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通過短信渠道A發(fā)送短信");
	}
}

短信渠道B SmsChannelServiceImplB.java

public class SmsChannelServiceImplB implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通過短信渠道B發(fā)送短信");
	}
}

通過工廠類來初始化所有短信渠道service

SmsChannelFactory.java

public class SmsChannelFactory {
	private Map<String,SmsChannelService> serviceMap;

	//初始化工廠,將所有的短信渠道Service放入Map中
	public SmsChannelFactory(){
		//渠道類型為 key , 對應(yīng)的服務(wù)類為value :
		serviceMap=new HashMap<String, SmsChannelService>(2);
		serviceMap.put("CHANNEL_A",new SmsChannelServiceImplA());
		serviceMap.put("CHANNEL_B",new SmsChannelServiceImplB());
	}

	//根據(jù)短信渠道類型獲得對應(yīng)渠道的Service
	public SmsChannelService buildService(String channelType){
		return serviceMap.get(channelType);
	}
}

在原來的SmsSendService中調(diào)用不同短信渠道的接口。
原來的 SmsSendService 類優(yōu)化如下

public class SmsSendService {

	private SmsChannelFactory smsChannelFactory;

	public SmsSendService(){
		smsChannelFactory=new SmsChannelFactory();
	}

	public void send(String phoneNo,String content){
		//從配置中讀取 短信渠道
		String channelType=config.getChannelType();
		//獲取渠道類型對應(yīng)的服務(wù)類
		SmsChannelService channelService=smsChannelFactory.buildService(channelType);
		//發(fā)送短信
		channelService.send(phoneNo,content);
	}

}

這樣SmsSendService類非常簡潔,把“if else"干掉了,
如果我要增加一個短信渠道C,無需再次更改 SmsSendService 類。
只需要增加一個類 SmsChannelServiceImplC 實現(xiàn) SmsChannelService 接口,
然后在工廠類 SmsChannelFactory 中增加一行初始化 SmsChannelServiceImplC 的代碼即可。

增加短信渠道C的實現(xiàn) SmsChannelServiceImplC.java

public class SmsChannelServiceImplC implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通過短信渠道C發(fā)送短信");
	}
}

修改工廠類 SmsChannelFactory.java

public class SmsChannelFactory {
	private Map<String,SmsChannelService> serviceMap;

	//初始化 serviceMap ,將所有的短信渠道Service放入Map中
	public SmsChannelFactory(){
		//渠道類型為 key , 對應(yīng)的服務(wù)類為value :
		serviceMap=new HashMap<String, SmsChannelService>(3);
		serviceMap.put("CHANNEL_A",new SmsChannelServiceImplA());
		serviceMap.put("CHANNEL_B",new SmsChannelServiceImplB());
		//ADD 增加一行 SmsChannelServiceImplC 的初始化代碼 
		serviceMap.put("CHANNEL_C",new SmsChannelServiceImplC());
	}

	//根據(jù)渠道類型構(gòu)建短信渠道Service
	public SmsChannelService buildService(String channelType){
		return serviceMap.get(channelType);
	}
}

“if else"是干掉了,但還是得修改原來的類 SmsChannelFactory ,不滿足"開閉原則",有沒有更好得方式呢?

我們通過使用spring的依賴注入進一步優(yōu)化代碼:

優(yōu)化代碼2

SmsChannelService 接口增加 getChannelType() 方法,這一步很關(guān)鍵。

public interface SmsChannelService {
	//發(fā)送短信
	void send(String phoneNo,String content);
	//關(guān)鍵:增加getChannelType()方法,子類實現(xiàn)這個方法用于標識出渠道類型
	String getChannelType();
}

子類增加該方法的實現(xiàn),并加上 @Service 注解,使其讓spring容器管理起來

SmsChannelServiceImplA.java

@Service
public class SmsChannelServiceImplA implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通過短信渠道A發(fā)送短信");
	}
	//關(guān)鍵:增加 getChannelType() 實現(xiàn)
	public String getChannelType() {
		return "CHANNEL_A";
	}
}

SmsChannelServiceImplB.java

@Service
public class SmsChannelServiceImplB implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通過短信渠道B發(fā)送短信");
	}
	//關(guān)鍵:增加 getChannelType() 實現(xiàn)
	public String getChannelType() {
		return "CHANNEL_B";
	}
}

修改 SmsChannelFactory 類: 這一步也很關(guān)鍵。

SmsChannelFactory.java

@Service
public class SmsChannelFactory {

	private Map<String,SmsChannelService> serviceMap;
	
	/*注入:通過spring容器將所有實現(xiàn) SmsChannelService 接口的類的實例注入到 serviceList 中*/
	@Autowired
	private List<SmsChannelService> serviceList;

	/*通過 @PostConstruct 注解,在 SmsChannelFactory 實例化后,來初始化 serviceMap */
	@PostConstruct
	private void init(){
		if(CollectionUtils.isEmpty(serviceList)){
			return ;
		}
		serviceMap=new HashMap<String, SmsChannelService>(serviceList.size());
		//將 serviceList 轉(zhuǎn)換為 serviceMap
		for (SmsChannelService channelService : serviceList) {
			String channelType=channelService.getChannelType();
			//重復性校驗,避免不同實現(xiàn)類的 getChannelType() 方法返回同一個值。
			if(serviceMap.get(channelType)!=null){
				throw new RuntimeException("同一個短信渠道只能有一個實現(xiàn)類");
			}
			/*渠道類型為 key , 對應(yīng)的服務(wù)類為value :
			與“優(yōu)化代碼1”中的通過手工設(shè)置“CHANNEL_A"、"CHANNEL_B"相比,
			這種方式更加自動化,后續(xù)在增加“CHANNEL_C"無需再改此處代碼*/
			serviceMap.put(channelType,channelService);
		}
	}

	//根據(jù)渠道類型獲取對應(yīng)短信渠道的Service
	public SmsChannelService buildService(String channelType){
		return serviceMap.get(channelType);
	}
}

SmsSendService 加上 @Service 注解。通過 @Autowired 注入 SmsChannelFactory

SmsSendService.java

@Service
public class SmsSendService {

	@Autowired
	private SmsChannelFactory smsChannelFactory;

	public void send(String phoneNo,String content){
		//從配置中讀取短信渠道類型
		String channelType=config.getChannelType();
		//構(gòu)建渠道類型對應(yīng)的服務(wù)類
		SmsChannelService channelService=smsChannelFactory.buildService(channelType);
		//發(fā)送短信
		channelService.send(phoneNo,content);
	}

}

這時,如果需要添加一個渠道C,那真的只需要添加一個 SmsChannelServiceImplC 即可,再也不用改原有代碼,完全遵循“開閉原則”。

SmsChannelServiceImplC.java

@Service
public class SmsChannelServiceImplC implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通過短信渠道C發(fā)送短信");
	}

	public String getChannelType() {
		return "CHANNEL_C";
	}
}

以上就是如何優(yōu)雅的替換掉Java代碼中的if else的詳細內(nèi)容,更多關(guān)于替換代碼中的if else的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解決IDEA刪除子模塊并重建后MAVEN無法識別的問題

    解決IDEA刪除子模塊并重建后MAVEN無法識別的問題

    這篇文章主要介紹了解決IDEA刪除子模塊并重建后MAVEN無法識別的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 快速掌握Java8中的Optional

    快速掌握Java8中的Optional

    Optional 是一個容器類,代表一個值存在或不存在,Optional并不是用來替換所有的null,而是為了在設(shè)計良好的API中更明確地表達可能缺失的值,這篇文章主要介紹了Java8的Optional及使用,需要的朋友可以參考下
    2023-07-07
  • springcloud連接遠程nacos失敗顯示localhost服務(wù)連接失敗的問題解決

    springcloud連接遠程nacos失敗顯示localhost服務(wù)連接失敗的問題解決

    這篇文章主要介紹了springcloud連接遠程nacos失敗顯示localhost服務(wù)連接失敗的問題解決,文中有詳細的代碼示例供大家參考,對大家解決問題有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • JVM執(zhí)行引擎和垃圾回收要點總結(jié)

    JVM執(zhí)行引擎和垃圾回收要點總結(jié)

    不論是在問題現(xiàn)場還是跳槽面試,我們面對JVM性能問題,依舊會束手無辭,它需要你對Java虛擬機的實現(xiàn)和優(yōu)化,有極為深刻的理解。所以我在這里整理了一下 JVM的知識點。今天說說虛擬機執(zhí)行引擎和垃圾回收,都是十足的干貨,請各位看官耐心批閱!
    2021-06-06
  • java轉(zhuǎn)換字符串編碼格式的方法

    java轉(zhuǎn)換字符串編碼格式的方法

    這篇文章主要介紹了java轉(zhuǎn)換字符串編碼格式的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • Springboot集成Springbrick實現(xiàn)動態(tài)插件的步驟詳解

    Springboot集成Springbrick實現(xiàn)動態(tài)插件的步驟詳解

    這篇文章主要介紹了Springboot集成Springbrick實現(xiàn)動態(tài)插件的詳細過程,文中的流程通過代碼示例介紹的非常詳細,感興趣的同學可以參考一下
    2023-06-06
  • Kotlin + Spring Boot 請求參數(shù)驗證的代碼實例

    Kotlin + Spring Boot 請求參數(shù)驗證的代碼實例

    本篇文章主要介紹了Kotlin + Spring Boot 請求參數(shù)驗證的代碼實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 深入探討JAVA中的異常與錯誤處理

    深入探討JAVA中的異常與錯誤處理

    這篇文章詳細介紹了JAVA中的異常與錯誤處理,有需要的朋友可以參考一下
    2013-09-09
  • @feignclient名字沖突的解決方案

    @feignclient名字沖突的解決方案

    這篇文章主要介紹了@feignclient名字沖突的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • java+io+swing實現(xiàn)學生信息管理系統(tǒng)

    java+io+swing實現(xiàn)學生信息管理系統(tǒng)

    這篇文章主要為大家詳細介紹了java+io+swing實現(xiàn)學生信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07

最新評論