新聞中心
本文轉(zhuǎn)載自微信公眾號(hào)「Java3y」,作者Java3y。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java3y公眾號(hào)。

為阿魯科爾沁等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及阿魯科爾沁網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都做網(wǎng)站、成都網(wǎng)站建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)、阿魯科爾沁網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
今天想來跟大家討論一下怎么干掉if else。
已經(jīng)工作的人可能深有體會(huì):沒有什么是if else搞不掂的,如果有,那就再嵌套一層。
大多數(shù)人都是做業(yè)務(wù)開發(fā)的,if else是避免不了的,但怎么讓if else的邏輯看起來更順眼,變得更加好看,更加好維護(hù)呢?
如果之前看過三歪文章的同學(xué)可能就會(huì)想到「責(zé)任鏈模式」。
沒錯(cuò)就是 責(zé)任鏈模式
當(dāng)你看到一個(gè)Service中有一大堆if else 邏輯的時(shí)候,可能你會(huì)幻想著要不要重構(gòu)掉,但是始終下不了手。
所以,今天想來分享一個(gè)「通用」的責(zé)任鏈模式的模板,把if else給套進(jìn)去就完事了,我相信都能學(xué)會(huì)。
之前寫設(shè)計(jì)模式文章的時(shí)候,有的同學(xué)會(huì)評(píng)論說我把東西搞復(fù)雜了,本來就有簡(jiǎn)單的方式去弄,為啥就要嵌套這么多層去搞這些花里胡哨的東西。
在我看來,用最簡(jiǎn)單的方式去實(shí)現(xiàn)是沒有任何問題的。但達(dá)到一定代碼量的時(shí)候,多想想一下,換一個(gè)人去維護(hù),人家能不能看懂,有沒有更加好的方式,這往往就需要「抽象」的能力。
這也是為什么這么多人推崇設(shè)計(jì)模式的原因。
不多BB,來吧。
責(zé)任鏈通用實(shí)現(xiàn)
現(xiàn)在我就默認(rèn)大家都知道什么是責(zé)任鏈模式了,如果還對(duì)這個(gè)不懂的同學(xué),可以先看看我之前的文章。
首先,我們會(huì)有一個(gè)業(yè)務(wù)執(zhí)行器接口,所有的業(yè)務(wù)實(shí)現(xiàn)都會(huì)實(shí)現(xiàn)該接口,這意味著上圖的邏輯A、B、C都會(huì)實(shí)現(xiàn)這個(gè)接口
- /**
- * 業(yè)務(wù)執(zhí)行器
- * @author 三歪
- */
- public interface BusinessProcess {
- void process(ProcessContext context);
- }
可以看到的是接口異常的簡(jiǎn)單,只有一個(gè)process處理的方法,方法接收的是ProcessContext
為什么process方法需要接收ProcessContext?很簡(jiǎn)單,我們?cè)谔幚磉壿婣、B、C的時(shí)候,可能邏輯B需要依賴邏輯A的處理結(jié)果。于是我們就需要有一個(gè)載體把這些給記錄下來。
所以,我們就有了ProcessContext,它代表的是責(zé)任鏈的上下文。
- /**
- * 責(zé)任鏈上下文
- * @author 3y
- */
- public class ProcessContext {
- // 標(biāo)識(shí)責(zé)任鏈的code
- private String code;
- // 存儲(chǔ)上下文的真正載體
- private Model model;
- // 責(zé)任鏈中斷的標(biāo)識(shí)
- private Boolean needBreak = false;
- }
現(xiàn)在責(zé)任鏈的執(zhí)行器和責(zé)任鏈所涉及的上下文都已經(jīng)有了,這意味著我們已經(jīng)有了責(zé)任鏈最主要的抽象了。
接下來就是我們需要把鏈給串起來,于是我們需要一個(gè)模板,其實(shí)我們做的就是用一個(gè)List來把BusinessProcess的子類給串起來。
- /**
- * 業(yè)務(wù)執(zhí)行模板(把責(zé)任鏈的邏輯串起來)
- * @author 3y
- */
- public class ProcessTemplate {
- private List
processList; - public List
getProcessList() { - return processList;
- }
- public void setProcessList(List
processList) { - this.processList = processList;
- }
- }
OK,現(xiàn)在我們已經(jīng)把責(zé)任鏈的整塊給抽象好了,接下來就是暴露流程控制器去執(zhí)行這個(gè)責(zé)任鏈:
- /**
- * 責(zé)任鏈的流程控制器(整個(gè)責(zé)任鏈的執(zhí)行流程通用控制)
- * @author 3y
- */
- @Data
- public class ProcessController {
- // 不同的code 對(duì)應(yīng)不同的責(zé)任鏈
- private Map
templateConfig = null; - public void process(ProcessContext context) {
- //根據(jù)上下文的Code 執(zhí)行不同的責(zé)任鏈
- String businessCode = context.getCode();
- ProcessTemplate processTemplate = templateConfig.get(businessCode);
- List
actionList = processTemplate.getProcessList(); - //遍歷某個(gè)責(zé)任鏈的流程節(jié)點(diǎn)
- for (BusinessProcess action : actionList) {
- try {
- action.process(context);
- if (context.getNeedBreak()) {
- break;
- }
- } catch (Exception e2) {
- //...
- }
- }
- }
- }
我們可以看到的是在ProcessController執(zhí)行鏈通用的流程控制器上會(huì)有一個(gè)Map去存儲(chǔ)多個(gè)責(zé)任鏈的模板,這樣做的好處就是:ProcessController這個(gè)流程控制器可以根據(jù)code支持多個(gè)責(zé)任鏈執(zhí)行。
接下來就是我們有具體的BusinessProcess去加入到ProcessTemplate的鏈上,然后調(diào)用ProcessController的方法去執(zhí)行整一條推送鏈。
一般我們?cè)赬ML注入就好了,比如說現(xiàn)在我們有兩個(gè)BusinessProcess的實(shí)現(xiàn),分別是白名單和發(fā)消息的邏輯:
- /**
- * 白名單處理器
- * @author 3y
- */
- @Service
- public class WhiteListProcess implements BusinessProcess {
- @Override
- public void process(ProcessContext context) {
- UserModel user = (UserModel) context.getModel();
- if ("3y".equals(user.getName())) {
- context.setNeedBreak(true);
- }
- }
- }
- /**
- * 發(fā)消息處理器
- * @author 三歪
- */
- @Service
- public class SendMessageProcess implements BusinessProcess {
- @Override
- public void process(ProcessContext context) {
- UserModel user = (UserModel) context.getModel();
- System.out.println("給"+user.getName()+"發(fā)消息");
- }
- }
然后我們把上面兩個(gè)處理器添加到ProcessTemplate的模板上,把ProcessTemplate添加到ProcessController的Map上:
然后我們?cè)诮涌诶镞厛?zhí)行這個(gè)責(zé)任鏈:
- @RestController
- public class UserController {
- @Autowired
- private ProcessController processController;
- @RequestMapping("/send")
- public void send(String userName) {
- // 構(gòu)建上下文
- ProcessContext processContext = new ProcessContext();
- UserModel userModel = new UserModel();
- userModel.setAge("24");
- userModel.setName(userName);
- processContext.setModel(userModel);
- processContext.setCode("sendMessage");
- processController.process(processContext);
- }
- }
我做了這么大的一套東西實(shí)現(xiàn)了什么功能?其實(shí)就一個(gè)if邏輯:
- if ("3y".equals(userModel.getName())) {
- return;
- }
- System.out.println("給" + userModel.getName() + "發(fā)消息");
下面我們還是來看看效果,從功能上我們可以發(fā)現(xiàn),只要我們輸入的不是「3y」,那就會(huì)打印消息
上面的邏輯,實(shí)際上就是一套通用的責(zé)任鏈的代碼,最核心的其實(shí)就是四個(gè)角色:「業(yè)務(wù)抽象接口」、「執(zhí)行過程中的上下文」、「將業(yè)務(wù)實(shí)現(xiàn)類串起來」和「一個(gè)通用的控制器執(zhí)行責(zé)任鏈」
如果沒看懂的同學(xué),三歪建議再對(duì)比一下代碼看看,責(zé)任鏈這種設(shè)計(jì)模式是非常好用,在項(xiàng)目里邊也是非常常見的。
只要把BusinessProcess/ProcessContext/ProcessTemplate/ProcessController的代碼給拷過去自己的項(xiàng)目中,這就能幫你把原有的if else邏輯給干掉。
Pipeline
不知道大家看過Pipeline這個(gè)詞了沒,在學(xué)Redis的時(shí)候可能會(huì)見過,在Redis里邊我們會(huì)用Pipeline去做批量的操作。
拋開Redis的Pipeline,但從宏觀的角度上來,Pipeline其實(shí)是一種架構(gòu)思想。
同時(shí)我也認(rèn)為它是「責(zé)任鏈模式」的實(shí)現(xiàn)之一。
下面來看看我這邊的一個(gè)Pipeline實(shí)現(xiàn)的架構(gòu)圖:
可以看到前人實(shí)現(xiàn)的Pipepline還是相對(duì)復(fù)雜的,沒有上面通用的責(zé)任鏈模式好理解,經(jīng)過分析可以看到都是換湯不換藥的。
下次再見到Pipeline這個(gè)詞的時(shí)候(因?yàn)檫@個(gè)詞還是很常見的),你們就應(yīng)該能想到責(zé)任鏈模式,然后你就發(fā)現(xiàn)你看懂了。
代碼GitHub:https://github.com/ZhongFuCheng3y/Java3yTestReposity
新聞標(biāo)題:三歪手把手教你干掉ifelse
網(wǎng)站地址:http://fisionsoft.com.cn/article/cccgcds.html


咨詢
建站咨詢
