电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

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

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

場景

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

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

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

代碼實現

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

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

爛代碼示例

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

SmsSendService.java

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…'

//... 此處省略部分代碼 ...//從配置中讀取 短信渠道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

public interface SmsChannelService{//發送短信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發送短信');}}

短信渠道B SmsChannelServiceImplB.java

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

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

SmsChannelFactory.java

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());}//根據短信渠道類型獲得對應渠道的Servicepublic SmsChannelService buildService(String channelType){return serviceMap.get(channelType);}}

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

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

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

修改工廠類 SmsChannelFactory.java

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());}//根據渠道類型構建短信渠道Servicepublic SmsChannelService buildService(String channelType){return serviceMap.get(channelType);}}

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

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

優化代碼2

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

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

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

SmsChannelServiceImplA.java

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

SmsChannelServiceImplB.java

@Servicepublic 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

@Servicepublic class SmsChannelFactory {private Map<String,SmsChannelService> serviceMap;/*注入:通過spring容器將所有實現 SmsChannelService 接口的類的實例注入到 serviceList 中*/@Autowiredprivate List<SmsChannelService> serviceList;/*通過 @PostConstruct 注解,在 SmsChannelFactory 實例化后,來初始化 serviceMap */@PostConstructprivate void init(){if(CollectionUtils.isEmpty(serviceList)){return ;}serviceMap=new HashMap<String, SmsChannelService>(serviceList.size());//將 serviceList 轉換為 serviceMapfor (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);}}//根據渠道類型獲取對應短信渠道的Servicepublic SmsChannelService buildService(String channelType){return serviceMap.get(channelType);}}

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

SmsSendService.java

@Servicepublic class SmsSendService {@Autowiredprivate 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

@Servicepublic 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的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 儿童语言障碍训练-武汉优佳加感统文化发展有限公司 | 空气能采暖,热泵烘干机,空气源热水机组|设备|厂家,东莞高温热泵_正旭新能源 | 南京蜂窝纸箱_南京木托盘_南京纸托盘-南京博恒包装有限公司 | 合景一建-无尘车间设计施工_食品医药洁净车间工程装修总承包公司 | 细沙回收机-尾矿干排脱水筛设备-泥石分离机-建筑垃圾分拣机厂家-青州冠诚重工机械有限公司 | 经济师考试_2025中级经济师报名时间_报名入口_考试时间_华课网校经济师培训网站 | HYDAC过滤器,HYDAC滤芯,现货ATOS油泵,ATOS比例阀-东莞市广联自动化科技有限公司 | 北京翻译公司-专业合同翻译-医学标书翻译收费标准-慕迪灵 | 外观设计_设备外观设计_外观设计公司_产品外观设计_机械设备外观设计_东莞工业设计公司-意品深蓝 | 福州仿石漆加盟_福建仿石漆厂家-外墙仿石漆加盟推荐铁壁金钢(福建)新材料科技有限公司有保障 | 广东恩亿梯电源有限公司【官网】_UPS不间断电源|EPS应急电源|模块化机房|电动汽车充电桩_UPS电源厂家(恩亿梯UPS电源,UPS不间断电源,不间断电源UPS) | 阜阳成人高考_阜阳成考报名时间_安徽省成人高考网 | 学叉车培训|叉车证报名|叉车查询|叉车证怎么考-工程机械培训网 | 东莞注册公司-代办营业执照-东莞公司注册代理记账-极刻财税 | 西门子伺服控制器维修-伺服驱动放大器-828D数控机床维修-上海涌迪 | 青州开防盗门锁-配汽车芯片钥匙-保险箱钥匙-吉祥修锁店 | LED灯杆屏_LED广告机_户外LED广告机_智慧灯杆_智慧路灯-太龙智显科技(深圳)有限公司 | 工业机械三维动画制作 环保设备原理三维演示动画 自动化装配产线三维动画制作公司-南京燃动数字 聚合氯化铝_喷雾聚氯化铝_聚合氯化铝铁厂家_郑州亿升化工有限公司 | 铜镍-康铜-锰铜-电阻合金-NC003 - 杭州兴宇合金有限公司 | 杭州|上海贴标机-百科| 风信子发稿-专注为企业提供全球新闻稿发布服务 | 美国PARKER齿轮泵,美国PARKER柱塞泵,美国PARKER叶片泵,美国PARKER电磁阀,美国PARKER比例阀-上海维特锐实业发展有限公司二部 | 报警器_家用防盗报警器_烟雾报警器_燃气报警器_防盗报警系统厂家-深圳市刻锐智能科技有限公司 | 杭州月嫂技术培训服务公司-催乳师培训中心报名费用-产后康复师培训机构-杭州优贝姆健康管理有限公司 | CCE素质教育博览会 | CCE素博会 | 教育展 | 美育展 | 科教展 | 素质教育展 | 棉服定制/厂家/公司_棉袄订做/价格/费用-北京圣达信棉服 | 列管冷凝器,刮板蒸发器,外盘管反应釜厂家-无锡曼旺化工设备有限公司 | 天津仓储物流-天津电商云仓-天津云仓一件代发-博程云仓官网 | 黑龙江「京科脑康」医院-哈尔滨失眠医院_哈尔滨治疗抑郁症医院_哈尔滨精神心理医院 | 广东成考网-广东成人高考网 | [官网]叛逆孩子管教_戒网瘾学校_全封闭问题青少年素质教育_新起点青少年特训学校 | 动库网动库商城-体育用品专卖店:羽毛球,乒乓球拍,网球,户外装备,运动鞋,运动包,运动服饰专卖店-正品运动品网上商城动库商城网 - 动库商城 | 天津蒸汽/热水锅炉-电锅炉安装维修直销厂家-天津鑫淼暖通设备有限公司 | SOUNDWELL 编码器|电位器|旋转编码器|可调电位器|编码开关厂家-广东升威电子制品有限公司 | ET3000双钳形接地电阻测试仪_ZSR10A直流_SXJS-IV智能_SX-9000全自动油介质损耗测试仪-上海康登 | 致胜管家软件服务【在线免费体验】| 广东恩亿梯电源有限公司【官网】_UPS不间断电源|EPS应急电源|模块化机房|电动汽车充电桩_UPS电源厂家(恩亿梯UPS电源,UPS不间断电源,不间断电源UPS) | 广西教师资格网-广西教师资格证考试网| 污水处理设备维修_污水处理工程改造_机械格栅_过滤设备_气浮设备_刮吸泥机_污泥浓缩罐_污水处理设备_污水处理工程-北京龙泉新禹科技有限公司 | 厦门网站建设_厦门网站设计_小程序开发_网站制作公司【麦格科技】 | 南京交通事故律师-专打交通事故的南京律师 |