国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 如何優雅的替換掉Java代碼中的if else

如何優雅的替換掉Java代碼中的if else

2020-09-09 00:24崔笑顏 Java教程

這篇文章主要介紹了如何優雅的替換掉Java代碼中的if else,幫助大家優化自己的Java代碼,提高可讀性與簡潔性,感興趣的朋友可以了解下

場景

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

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

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

代碼實現

上面的業務場景簡單來說就是:針對不同的短信渠道來調用對應的短信平臺接口實現短信發送。
短信渠道一般配置在文件中,或者配置在數據庫中。

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

爛代碼示例

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

SmsSendService.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class SmsSendService{
    /**
     * @Param phoneNo 手機號
     * @Param content 短信內容
     */
    public void send(String phoneNo,String content){
        //從配置中讀取 短信渠道
        String channelType=config.getChannelType();
        
        //如果是短信渠道A,則調用渠道A的api發送
        if(Objects.equals(channelType,"CHANNEL_A")){
            System.out.println("通過短信渠道A發送短信");
        }
        //如果是短信渠道B,則調用渠道B的api發送
        else if(Objects.equals(channelType,"CHANNEL_B")){
            System.out.println("通過短信渠道B發送短信");
        }
    }
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//... 此處省略部分代碼 ...
 
//從配置中讀取 短信渠道
String channelType=config.getChannelType();
//如果是短信渠道A,則調用渠道A的api發送
if(Objects.equals(channelType,"CHANNEL_A")){
    System.out.println("通過短信渠道A發送短信");
}
//如果是短信渠道B,則調用渠道B的api發送
else if(Objects.equals(channelType,"CHANNEL_B")){
    System.out.println("通過短信渠道B發送短信");
}
//ADD: 如果是短信渠道C,則調用渠道C的api發送
else if(Objects.equals(channelType,"CHANNEL_C")){
    System.out.println("通過短信渠道C發送短信");
}
 
//... 此處省略部分代碼 ...

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

優化代碼1

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

短信渠道接口 SmsChannelService.java

?
1
2
3
4
public interface SmsChannelService{
    //發送短信
    void send(String phoneNo,String content);
}

短信渠道A SmsChannelServiceImplA.java

?
1
2
3
4
5
public class SmsChannelServiceImplA implements SmsChannelService {
    public void send(String phoneNo, String content) {
        System.out.println("通過短信渠道A發送短信");
    }
}

短信渠道B SmsChannelServiceImplB.java

?
1
2
3
4
5
public class SmsChannelServiceImplB implements SmsChannelService {
    public void send(String phoneNo, String content) {
        System.out.println("通過短信渠道B發送短信");
    }
}

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

SmsChannelFactory.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SmsChannelFactory {
    private Map<String,SmsChannelService> serviceMap;
 
    //初始化工廠,將所有的短信渠道Service放入Map中
    public SmsChannelFactory(){
        //渠道類型為 key , 對應的服務類為value :
        serviceMap=new HashMap<String, SmsChannelService>(2);
        serviceMap.put("CHANNEL_A",new SmsChannelServiceImplA());
        serviceMap.put("CHANNEL_B",new SmsChannelServiceImplB());
    }
 
    //根據短信渠道類型獲得對應渠道的Service
    public SmsChannelService buildService(String channelType){
        return serviceMap.get(channelType);
    }
}

在原來的SmsSendService中調用不同短信渠道的接口。
原來的 SmsSendService 類優化如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SmsSendService {
 
    private SmsChannelFactory smsChannelFactory;
 
    public SmsSendService(){
        smsChannelFactory=new SmsChannelFactory();
    }
 
    public void send(String phoneNo,String content){
        //從配置中讀取 短信渠道
        String channelType=config.getChannelType();
        //獲取渠道類型對應的服務類
        SmsChannelService channelService=smsChannelFactory.buildService(channelType);
        //發送短信
        channelService.send(phoneNo,content);
    }
 
}

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

增加短信渠道C的實現 SmsChannelServiceImplC.java

?
1
2
3
4
5
public class SmsChannelServiceImplC implements SmsChannelService {
    public void send(String phoneNo, String content) {
        System.out.println("通過短信渠道C發送短信");
    }
}

修改工廠類 SmsChannelFactory.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SmsChannelFactory {
    private Map<String,SmsChannelService> serviceMap;
 
    //初始化 serviceMap ,將所有的短信渠道Service放入Map中
    public SmsChannelFactory(){
        //渠道類型為 key , 對應的服務類為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());
    }
 
    //根據渠道類型構建短信渠道Service
    public SmsChannelService buildService(String channelType){
        return serviceMap.get(channelType);
    }
}

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

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

優化代碼2

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

?
1
2
3
4
5
6
public interface SmsChannelService {
    //發送短信
    void send(String phoneNo,String content);
    //關鍵:增加getChannelType()方法,子類實現這個方法用于標識出渠道類型
    String getChannelType();
}

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

SmsChannelServiceImplA.java

?
1
2
3
4
5
6
7
8
9
10
@Service
public class SmsChannelServiceImplA implements SmsChannelService {
    public void send(String phoneNo, String content) {
        System.out.println("通過短信渠道A發送短信");
    }
    //關鍵:增加 getChannelType() 實現
    public String getChannelType() {
        return "CHANNEL_A";
    }
}

SmsChannelServiceImplB.java

?
1
2
3
4
5
6
7
8
9
10
@Service
public class SmsChannelServiceImplB implements SmsChannelService {
    public void send(String phoneNo, String content) {
        System.out.println("通過短信渠道B發送短信");
    }
    //關鍵:增加 getChannelType() 實現
    public String getChannelType() {
        return "CHANNEL_B";
    }
}

修改 SmsChannelFactory 類: 這一步也很關鍵。

SmsChannelFactory.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Service
public class SmsChannelFactory {
 
    private Map<String,SmsChannelService> serviceMap;
    
    /*注入:通過spring容器將所有實現 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 轉換為 serviceMap
        for (SmsChannelService channelService : serviceList) {
            String channelType=channelService.getChannelType();
            //重復性校驗,避免不同實現類的 getChannelType() 方法返回同一個值。
            if(serviceMap.get(channelType)!=null){
                throw new RuntimeException("同一個短信渠道只能有一個實現類");
            }
            /*渠道類型為 key , 對應的服務類為value :
            與“優化代碼1”中的通過手工設置“CHANNEL_A"、"CHANNEL_B"相比,
            這種方式更加自動化,后續在增加“CHANNEL_C"無需再改此處代碼*/
            serviceMap.put(channelType,channelService);
        }
    }
 
    //根據渠道類型獲取對應短信渠道的Service
    public SmsChannelService buildService(String channelType){
        return serviceMap.get(channelType);
    }
}

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

SmsSendService.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Service
public class SmsSendService {
 
    @Autowired
    private SmsChannelFactory smsChannelFactory;
 
    public void send(String phoneNo,String content){
        //從配置中讀取短信渠道類型
        String channelType=config.getChannelType();
        //構建渠道類型對應的服務類
        SmsChannelService channelService=smsChannelFactory.buildService(channelType);
        //發送短信
        channelService.send(phoneNo,content);
    }
 
}

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

SmsChannelServiceImplC.java

?
1
2
3
4
5
6
7
8
9
10
@Service
public class SmsChannelServiceImplC implements SmsChannelService {
    public void send(String phoneNo, String content) {
        System.out.println("通過短信渠道C發送短信");
    }
 
    public String getChannelType() {
        return "CHANNEL_C";
    }
}

以上就是如何優雅的替換掉Java代碼中的if else的詳細內容,更多關于替換代碼中的if else的資料請關注服務器之家其它相關文章!

原文鏈接:https://cloud.tencent.com/developer/article/1640062

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品不卡一区 | 欧美在线网站 | 国内精品久久久久久 | 亚洲一区中文 | 国产在线中文字幕 | 国产狂做受xxxxx高潮 | 欧美久久久久久久 | 播放欧美一级片 | 天天干天天草 | 亚洲a在线观看 | 日本一区二区三区中文字幕 | 亚洲视频区 | 日韩精品一区二区三区中文在线 | 超碰在线99 | 国产一区二区久久 | 操操操小说 | 久久亚洲国产 | 亚洲福利影院 | 免费a级毛片在线观看 | 岛国搬运工av在线播放 | 国产一区二区三区视频在线观看 | 日韩av高清 | 在线视频不卡一区 | 亚洲第一av| 高清中文字幕 | 荷兰欧美一级毛片 | 青青草草 | 一本大道综合伊人精品热热 | 最近韩国日本免费观看mv免费版 | 97久久精品 | 91久久综合亚洲鲁鲁五月天 | 成人av在线网| 女男羞羞视频网站免费 | 日韩美女视频 | 久久久久久亚洲精品 | 黄色小视频免费 | 国产黄大片 | 香蕉久久av一区二区三区 | 国产欧美精品在线 | 色婷婷一区二区三区 | 日韩综合网 |