自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

三歪手把手教你干掉if else

開發(fā) 前端
今天想來跟大家討論一下怎么干掉if else。已經(jīng)工作的人可能深有體會:沒有什么是if else搞不掂的,如果有,那就再嵌套一層。

 [[332944]]

本文轉(zhuǎn)載自微信公眾號「Java3y」,作者Java3y。轉(zhuǎn)載本文請聯(lián)系Java3y公眾號。

今天想來跟大家討論一下怎么干掉if else。

已經(jīng)工作的人可能深有體會:沒有什么是if else搞不掂的,如果有,那就再嵌套一層。

大多數(shù)人都是做業(yè)務(wù)開發(fā)的,if else是避免不了的,但怎么讓if else的邏輯看起來更順眼,變得更加好看,更加好維護(hù)呢?

如果之前看過三歪文章的同學(xué)可能就會想到「責(zé)任鏈模式」。

沒錯就是 責(zé)任鏈模式

當(dāng)你看到一個Service中有一大堆if else 邏輯的時候,可能你會幻想著要不要重構(gòu)掉,但是始終下不了手。

所以,今天想來分享一個「通用」的責(zé)任鏈模式的模板,把if else給套進(jìn)去就完事了,我相信都能學(xué)會。

之前寫設(shè)計(jì)模式文章的時候,有的同學(xué)會評論說我把東西搞復(fù)雜了,本來就有簡單的方式去弄,為啥就要嵌套這么多層去搞這些花里胡哨的東西。

在我看來,用最簡單的方式去實(shí)現(xiàn)是沒有任何問題的。但達(dá)到一定代碼量的時候,多想想一下,換一個人去維護(hù),人家能不能看懂,有沒有更加好的方式,這往往就需要「抽象」的能力。

這也是為什么這么多人推崇設(shè)計(jì)模式的原因。

不多BB,來吧。

責(zé)任鏈通用實(shí)現(xiàn)

現(xiàn)在我就默認(rèn)大家都知道什么是責(zé)任鏈模式了,如果還對這個不懂的同學(xué),可以先看看我之前的文章。

 

首先,我們會有一個業(yè)務(wù)執(zhí)行器接口,所有的業(yè)務(wù)實(shí)現(xiàn)都會實(shí)現(xiàn)該接口,這意味著上圖的邏輯A、B、C都會實(shí)現(xiàn)這個接口

  1. /** 
  2.  * 業(yè)務(wù)執(zhí)行器 
  3.  * @author 三歪 
  4.  */ 
  5. public interface BusinessProcess { 
  6.     void process(ProcessContext context); 

可以看到的是接口異常的簡單,只有一個process處理的方法,方法接收的是ProcessContext

為什么process方法需要接收ProcessContext?很簡單,我們在處理邏輯A、B、C的時候,可能邏輯B需要依賴邏輯A的處理結(jié)果。于是我們就需要有一個載體把這些給記錄下來。

所以,我們就有了ProcessContext,它代表的是責(zé)任鏈的上下文。

  1. /** 
  2.  * 責(zé)任鏈上下文 
  3.  * @author 3y 
  4.  */ 
  5. public class ProcessContext { 
  6.     // 標(biāo)識責(zé)任鏈的code 
  7.     private String code; 
  8.     // 存儲上下文的真正載體 
  9.     private Model model; 
  10.     // 責(zé)任鏈中斷的標(biāo)識 
  11.     private Boolean needBreak = false

現(xiàn)在責(zé)任鏈的執(zhí)行器和責(zé)任鏈所涉及的上下文都已經(jīng)有了,這意味著我們已經(jīng)有了責(zé)任鏈最主要的抽象了。

接下來就是我們需要把鏈給串起來,于是我們需要一個模板,其實(shí)我們做的就是用一個List來把BusinessProcess的子類給串起來。

  1. /** 
  2.  * 業(yè)務(wù)執(zhí)行模板(把責(zé)任鏈的邏輯串起來) 
  3.  * @author 3y 
  4.  */ 
  5. public class ProcessTemplate { 
  6.     private List<BusinessProcess> processList; 
  7.     public List<BusinessProcess> getProcessList() { 
  8.         return processList; 
  9.     } 
  10.     public void setProcessList(List<BusinessProcess> processList) { 
  11.         this.processList = processList; 
  12.     } 

OK,現(xiàn)在我們已經(jīng)把責(zé)任鏈的整塊給抽象好了,接下來就是暴露流程控制器去執(zhí)行這個責(zé)任鏈:

  1. /** 
  2.  * 責(zé)任鏈的流程控制器(整個責(zé)任鏈的執(zhí)行流程通用控制) 
  3.  * @author 3y  
  4.  */ 
  5. @Data 
  6. public class ProcessController { 
  7.      
  8.     // 不同的code 對應(yīng)不同的責(zé)任鏈 
  9.     private Map<String, ProcessTemplate> templateConfig = null
  10.  
  11.     public void process(ProcessContext context) { 
  12.         //根據(jù)上下文的Code 執(zhí)行不同的責(zé)任鏈 
  13.         String businessCode = context.getCode(); 
  14.         ProcessTemplate processTemplate = templateConfig.get(businessCode); 
  15.         List<BusinessProcess> actionList = processTemplate.getProcessList(); 
  16.         //遍歷某個責(zé)任鏈的流程節(jié)點(diǎn) 
  17.         for (BusinessProcess action : actionList) { 
  18.             try { 
  19.                 action.process(context); 
  20.                 if (context.getNeedBreak()) { 
  21.                     break; 
  22.                 } 
  23.             } catch (Exception e2) { 
  24.                 //... 
  25.             } 
  26.         } 
  27.     } 

我們可以看到的是在ProcessController執(zhí)行鏈通用的流程控制器上會有一個Map去存儲多個責(zé)任鏈的模板,這樣做的好處就是:ProcessController這個流程控制器可以根據(jù)code支持多個責(zé)任鏈執(zhí)行。

接下來就是我們有具體的BusinessProcess去加入到ProcessTemplate的鏈上,然后調(diào)用ProcessController的方法去執(zhí)行整一條推送鏈。

一般我們在XML注入就好了,比如說現(xiàn)在我們有兩個BusinessProcess的實(shí)現(xiàn),分別是白名單和發(fā)消息的邏輯:

  1. /** 
  2.  * 白名單處理器 
  3.  * @author 3y 
  4.  */ 
  5. @Service 
  6. public class WhiteListProcess implements BusinessProcess { 
  7.     @Override 
  8.     public void process(ProcessContext context) { 
  9.         UserModel user = (UserModel) context.getModel(); 
  10.         if ("3y".equals(user.getName())) { 
  11.             context.setNeedBreak(true); 
  12.         } 
  13.     } 
  14.  
  15. /** 
  16.  * 發(fā)消息處理器 
  17.  * @author 三歪 
  18.  */ 
  19. @Service 
  20. public class SendMessageProcess implements BusinessProcess { 
  21.  
  22.     @Override 
  23.     public void process(ProcessContext context) { 
  24.         UserModel user = (UserModel) context.getModel(); 
  25.         System.out.println("給"+user.getName()+"發(fā)消息"); 
  26.     } 

然后我們把上面兩個處理器添加到ProcessTemplate的模板上,把ProcessTemplate添加到ProcessController的Map上:

  1. <!--發(fā)送消息的責(zé)任鏈--> 
  2. <bean id="sendMessageTemplate" class="com.chainofresponsibility.ProcessTemplate"
  3.   <property name="processList"
  4.     <list> 
  5.       <ref bean="whiteListProcess"></ref> 
  6.       <ref bean="sendMessageProcess"></ref> 
  7.     </list> 
  8.   </property> 
  9. </bean> 
  10.  
  11. <!--通用流程處理器,維護(hù)多條責(zé)任鏈--> 
  12. <bean id="processController" class="com.chainofresponsibility.ProcessController"
  13.   <property name="templateConfig"
  14.     <map> 
  15.       <entry key="sendMessage" value-ref="sendMessageTemplate" /> 
  16.     </map> 
  17.   </property> 
  18. </bean> 

然后我們在接口里邊執(zhí)行這個責(zé)任鏈:

  1. @RestController 
  2. public class UserController { 
  3.     @Autowired 
  4.     private ProcessController processController; 
  5.  
  6.     @RequestMapping("/send"
  7.     public void  send(String userName) { 
  8.         // 構(gòu)建上下文 
  9.         ProcessContext processContext = new ProcessContext(); 
  10.  
  11.         UserModel userModel = new UserModel(); 
  12.         userModel.setAge("24"); 
  13.         userModel.setName(userName); 
  14.         processContext.setModel(userModel); 
  15.  
  16.         processContext.setCode("sendMessage"); 
  17.  
  18.         processController.process(processContext); 
  19.     } 

我做了這么大的一套東西實(shí)現(xiàn)了什么功能?其實(shí)就一個if邏輯:

  1. if ("3y".equals(userModel.getName())) { 
  2.   return
  3. System.out.println("給" + userModel.getName() + "發(fā)消息"); 

下面我們還是來看看效果,從功能上我們可以發(fā)現(xiàn),只要我們輸入的不是「3y」,那就會打印消息

 

上面的邏輯,實(shí)際上就是一套通用的責(zé)任鏈的代碼,最核心的其實(shí)就是四個角色:「業(yè)務(wù)抽象接口」、「執(zhí)行過程中的上下文」、「將業(yè)務(wù)實(shí)現(xiàn)類串起來」和「一個通用的控制器執(zhí)行責(zé)任鏈」

 

如果沒看懂的同學(xué),三歪建議再對比一下代碼看看,責(zé)任鏈這種設(shè)計(jì)模式是非常好用,在項(xiàng)目里邊也是非常常見的。

只要把BusinessProcess/ProcessContext/ProcessTemplate/ProcessController的代碼給拷過去自己的項(xiàng)目中,這就能幫你把原有的if else邏輯給干掉。

Pipeline

不知道大家看過Pipeline這個詞了沒,在學(xué)Redis的時候可能會見過,在Redis里邊我們會用Pipeline去做批量的操作。

拋開Redis的Pipeline,但從宏觀的角度上來,Pipeline其實(shí)是一種架構(gòu)思想。

同時我也認(rèn)為它是「責(zé)任鏈模式」的實(shí)現(xiàn)之一。

下面來看看我這邊的一個Pipeline實(shí)現(xiàn)的架構(gòu)圖:

 

可以看到前人實(shí)現(xiàn)的Pipepline還是相對復(fù)雜的,沒有上面通用的責(zé)任鏈模式好理解,經(jīng)過分析可以看到都是換湯不換藥的。

下次再見到Pipeline這個詞的時候(因?yàn)檫@個詞還是很常見的),你們就應(yīng)該能想到責(zé)任鏈模式,然后你就發(fā)現(xiàn)你看懂了。

代碼GitHub:https://github.com/ZhongFuCheng3y/Java3yTestReposity

 

責(zé)任編輯:武曉燕 來源: Java3y
相關(guān)推薦

2021-07-14 09:00:00

JavaFX開發(fā)應(yīng)用

2011-01-10 14:41:26

2011-05-03 15:59:00

黑盒打印機(jī)

2022-01-08 20:04:20

攔截系統(tǒng)調(diào)用

2022-03-14 14:47:21

HarmonyOS操作系統(tǒng)鴻蒙

2023-04-26 12:46:43

DockerSpringKubernetes

2022-12-07 08:42:35

2022-07-27 08:16:22

搜索引擎Lucene

2021-02-26 11:54:38

MyBatis 插件接口

2011-02-22 13:46:27

微軟SQL.NET

2021-12-28 08:38:26

Linux 中斷喚醒系統(tǒng)Linux 系統(tǒng)

2017-07-07 11:01:04

Spark性能調(diào)優(yōu)

2020-08-12 07:41:39

SQL 優(yōu)化語句

2021-07-01 09:31:50

MySQL SQL 語句數(shù)據(jù)庫

2024-04-02 08:58:13

2010-09-16 14:08:13

無線雙網(wǎng)

2023-03-27 08:28:57

spring代碼,starter

2011-04-28 15:09:15

jQueryjqPlot

2017-10-20 13:41:11

Spark集群代碼

2024-03-05 18:27:43

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號