国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

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

瀏覽:5日期:2022-08-25 11:34:22

場(chǎng)景

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

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

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

代碼實(shí)現(xiàn)

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

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

爛代碼示例

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

SmsSendService.java

public class SmsSendService{/** * @Param phoneNo 手機(jī)號(hào) * @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('通過(guò)短信渠道A發(fā)送短信');}//如果是短信渠道B,則調(diào)用渠道B的api發(fā)送else if(Objects.equals(channelType,'CHANNEL_B')){System.out.println('通過(guò)短信渠道B發(fā)送短信');}}}

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

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

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

優(yōu)化代碼1

定義一個(gè)短信渠道的接口 SmsChannelService,所有的短信渠道API都實(shí)現(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('通過(guò)短信渠道A發(fā)送短信');}}

短信渠道B SmsChannelServiceImplB.java

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

通過(guò)工廠類來(lái)初始化所有短信渠道service

SmsChannelFactory.java

public class SmsChannelFactory {private Map<String,SmsChannelService> serviceMap;//初始化工廠,將所有的短信渠道Service放入Map中public SmsChannelFactory(){//渠道類型為 key , 對(duì)應(yīng)的服務(wù)類為value :serviceMap=new HashMap<String, SmsChannelService>(2);serviceMap.put('CHANNEL_A',new SmsChannelServiceImplA());serviceMap.put('CHANNEL_B',new SmsChannelServiceImplB());}//根據(jù)短信渠道類型獲得對(duì)應(yīng)渠道的Servicepublic SmsChannelService buildService(String channelType){return serviceMap.get(channelType);}}

在原來(lái)的SmsSendService中調(diào)用不同短信渠道的接口。原來(lái)的 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();//獲取渠道類型對(duì)應(yīng)的服務(wù)類SmsChannelService channelService=smsChannelFactory.buildService(channelType);//發(fā)送短信channelService.send(phoneNo,content);}}

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

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

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

修改工廠類 SmsChannelFactory.java

public class SmsChannelFactory {private Map<String,SmsChannelService> serviceMap;//初始化 serviceMap ,將所有的短信渠道Service放入Map中public SmsChannelFactory(){//渠道類型為 key , 對(duì)應(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)建短信渠道Servicepublic SmsChannelService buildService(String channelType){return serviceMap.get(channelType);}}

“if else'是干掉了,但還是得修改原來(lái)的類 SmsChannelFactory ,不滿足'開閉原則',有沒(méi)有更好得方式呢?

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

優(yōu)化代碼2

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

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

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

SmsChannelServiceImplA.java

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

SmsChannelServiceImplB.java

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

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

SmsChannelFactory.java

@Servicepublic class SmsChannelFactory {private Map<String,SmsChannelService> serviceMap;/*注入:通過(guò)spring容器將所有實(shí)現(xiàn) SmsChannelService 接口的類的實(shí)例注入到 serviceList 中*/@Autowiredprivate List<SmsChannelService> serviceList;/*通過(guò) @PostConstruct 注解,在 SmsChannelFactory 實(shí)例化后,來(lái)初始化 serviceMap */@PostConstructprivate void init(){if(CollectionUtils.isEmpty(serviceList)){return ;}serviceMap=new HashMap<String, SmsChannelService>(serviceList.size());//將 serviceList 轉(zhuǎn)換為 serviceMapfor (SmsChannelService channelService : serviceList) {String channelType=channelService.getChannelType();//重復(fù)性校驗(yàn),避免不同實(shí)現(xiàn)類的 getChannelType() 方法返回同一個(gè)值。if(serviceMap.get(channelType)!=null){throw new RuntimeException('同一個(gè)短信渠道只能有一個(gè)實(shí)現(xiàn)類');}/*渠道類型為 key , 對(duì)應(yīng)的服務(wù)類為value :與“優(yōu)化代碼1”中的通過(guò)手工設(shè)置“CHANNEL_A'、'CHANNEL_B'相比,這種方式更加自動(dòng)化,后續(xù)在增加“CHANNEL_C'無(wú)需再改此處代碼*/serviceMap.put(channelType,channelService);}}//根據(jù)渠道類型獲取對(duì)應(yīng)短信渠道的Servicepublic SmsChannelService buildService(String channelType){return serviceMap.get(channelType);}}

SmsSendService 加上 @Service 注解。通過(guò) @Autowired 注入 SmsChannelFactory

SmsSendService.java

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

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

SmsChannelServiceImplC.java

@Servicepublic class SmsChannelServiceImplC implements SmsChannelService {public void send(String phoneNo, String content) {System.out.println('通過(guò)短信渠道C發(fā)送短信');}public String getChannelType() {return 'CHANNEL_C';}}

以上就是如何優(yōu)雅的替換掉Java代碼中的if else的詳細(xì)內(nèi)容,更多關(guān)于替換代碼中的if else的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 国产香港特级一级毛片 | 最新主播福利视频在线观看 | 91久久香蕉国产线看 | 国产精品久久久久影视不卡 | 国产成人午夜精品影院游乐网 | 最近手机高清中文字幕大全7 | 成人毛片视频免费网站观看 | 亚洲第一se情网站 | 美国三级网 | 成人免费视频69 | 欧美成人手机视频 | 高清一区在线 | 91影视永久福利免费观看 | 男女做性免费视频软件 | 日韩在线观看一区 | 中国黄色一级大片 | 久久影院国产 | 欧美一级片 在线播放 | 免费人成黄页网站在线观看 | 国产91无套剧情在线播放 | 久久亚洲精品中文字幕亚瑟 | 亚洲成人第一页 | 一本色道久久88加勒比—综合 | 久久精品视频久久 | 日本xxxxx黄区免费看动漫 | 欧美成人一级视频 | 怡红院在线视频观看 | 国产精品三级a三级三级午夜 | 91免费视| 男人天堂男人天堂 | 亚洲男同可播放videos | 日本一级毛片高清免费观看视频 | 精品视频一区二区三区免费 | 国产一区亚洲一区 | 又粗又爽又色男女乱淫播放男女 | 国产精品黄页网站在线播放免费 | 男操女视频 | 中文字幕视频网站 | 亚洲精品资源网在线观看 | 亚洲欧美中文字幕在线网站 | 久久黄色网址 |