<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          不吹牛X,我真的干掉了if-else

          共 3340字,需瀏覽 7分鐘

           ·

          2021-05-06 03:36


          c83a426316aa7400c35c8f94ec171266.webp

          新手發(fā)文,在線求關(guān)注

          8ca177126793110ebc77247c3a4c2618.webp

          我們在web開發(fā)中,經(jīng)常使用數(shù)據(jù)庫表中的字段作為“標記”來表示多個“狀態(tài)”,比如:

          我們就以某寶的在線購物流程為例進行分析。在訂單表中,使用zt字段來表示訂單的狀態(tài),常見的狀態(tài)就有:

          = 狀態(tài)碼表示?=

          0

          待付款

          1

          待發(fā)貨

          2

          待收貨

          3

          待評價

          4

          售后

          當我們想按條件查詢各個類型的訂單的時候,只需要一個接口,在前端傳入相應(yīng)的狀態(tài)碼就可以了。在dao層大概也就是通過如下的語句進行查詢:

          select?* from?orders where?zt = #{zt}

          如何才能有很高的擴展性?

          假設(shè)有這么幾個“不成需求的需求”:

          1. 我想讓待收貨的訂單按照訂單發(fā)貨時間或者預計送達時間排序,其他的暫且按照訂單創(chuàng)建時間排序吧

          2. 想將“待收貨”的狀態(tài)區(qū)分開,分為“用戶未收到貨”和“用戶收到貨但是未點擊確認收貨按鈕”兩種狀態(tài)

          常規(guī)方式如何解決?

          • 需求一(不同的狀態(tài)處理方式不同):

            這個很容易的,在sevice層添加一個判斷就可以,其他的代碼不用改,代碼如下:

          // 2 表示待收貨
          if(zt == 2){
          ?//按照需求,按照訂單發(fā)貨時間或者預計送達時間排序
          }else{
          ?//其他狀態(tài)的訂單,全部按照訂單創(chuàng)建時間排序
          }

          上邊這個代碼的修改量已經(jīng)很小了,但是如果我要把各種不同的狀態(tài)訂單全部按照不同的排序方式排序呢?你可能會寫如下代碼

          if(zt==0){
          ?// 待付款的訂單處理代碼...
          }else?if(zt==1){
          ?
          }else?if(zt==2){
          ?
          }else?if(zt==3){
          ?
          }else?if(zt==4){
          ?
          }

          上邊代碼太low了,有些小伙伴可能會使用switch進行優(yōu)化(這里就不寫代碼了,因為和上邊并沒有任何區(qū)別)。

          • 需求二(添加一個新的狀態(tài)表示):

            這也很easy啊,直接在上邊的if-else或者switch代碼中添加新的狀態(tài)判斷不就好了。

          思考如何干掉if-else?

          上邊的方式可以完成我們的需求,但是有以下幾點不足:

          1. 面對“各種各樣奇怪的需求”,我們要頻繁地修改上邊的代碼,時間久了,豈不成了渣渣。甚至我們自己都不愿意再去看這些代碼了;

          2. 如果新增加一個狀態(tài)表示,也就是給zt字段新的狀態(tài)含義表示,我們又要添加if-else,這太復雜了。

          使用策略模式來解決if-else的問題

          是的,就是使用策略模式來解決進行太多的狀態(tài)判斷代碼就是一個好辦法。比如,就上邊每一個if-else中的代碼抽成一個類或者方法進行處理。

          主要的代碼我就不寫了,因為下邊才是我們的主菜,這里說的這種方式只能解決if-else里邊的代碼復雜問題,將代碼進行一定程度上的解耦。但并沒有實質(zhì)地解決if-else的問題,而且這也是網(wǎng)上大多數(shù)的解決辦法。

          如果對策略模式不太了解的小伙伴,可以看下這篇文章,不看也沒關(guān)系,在下邊你會看到怎么用的。

          嘗試使用Spring來配合策略模式

          程序設(shè)計的一大原則“對擴展開放,對修改關(guān)閉”,定義一個接口類,用來查詢不同狀態(tài)的訂單列表。如下:

          public?interface?OrderService?{

          ???/**
          ????* 查詢對應(yīng)狀態(tài)的訂單列表
          ????* @param?zt
          ????* @return
          ????*/

          ???List<Order> getOrderList(String zt);
          }

          然后根據(jù)不同的訂單狀態(tài)創(chuàng)建不同的實現(xiàn)類,比如,“待付款”的訂單查詢類如下:

          雖然以下的命名方式屬于錯誤示范,但是卻能很好地理解

          @Service("orderServiceDfk") // 這個命名確實很不友好,但是我相信你能理解哈
          public?class?PendingParymentOrderSeviceImpl?implements?OrderService?{
          ???/**
          ????* 查詢待付款的訂單列表
          ????*
          ????* @param?zt
          ????* @return
          ????*/

          ???@Override
          ???public?List<Order> getOrderList(String zt)?{
          ?????//這里要利用dao層從數(shù)據(jù)庫中查詢出來相應(yīng)的訂單列表
          ?????return?null;
          ??}

          看了這兩個類的代碼,我相信小伙伴們應(yīng)該能理解了要怎么做了,就是根據(jù)前端傳來不同的zt值,后臺使用不同的類來處理,但是我們可以通過Spring來完全取掉if-else。

          我們的controller層代碼如下:

          @RestController
          public?class?OrderController {
          ?private?String?orderServiceBeanNamePrefix = "orderService";

          ?@RequestMapping("getOrderList/{zt}")
          ?public?List<Order> getOrderList(@PathVariable("zt") String?zt) {

          ???//獲取對應(yīng)的處理狀態(tài)的bean來處理
          ???//就通過這樣一句代碼,完全解決了if-else的判斷邏輯
          ???OrderService orderService = (OrderService) SpingContext.getBean(orderServiceBeanNamePrefix + zt);
          ???List<Order> orderList = orderService.getOrderList();

          ???return?orderList;
          }
          }

          上邊用了一個工具類,就是從Spring 容器中獲取相應(yīng)的bean,代碼如下:

          /**
          * 微信公眾號 “小魚與Java”
          *
          * 原理很簡單,我們寫的類實現(xiàn)這個接口,具體可以查閱Spring生命周期相關(guān)內(nèi)容
          * Spring會自動調(diào)用其中的setApplicationContext方法,傳入Spring容器上下文
          * 我們就在這里把Spring上下文保存下來
          *
          * @date?2020/5/18
          * @auther?Lyn4ever
          */

          @Component
          public?class?SpingContext?implements?ApplicationContextAware?{

          ???private?static?ApplicationContext applicationContext;

          ???/**
          ????* 根據(jù)name從Spring容器中獲取bean
          ????* @param?name
          ????* @return
          ????*/

          ???public?static?Object getBean(String name){
          ???????return?applicationContext.getBean(name);
          ??}

          ???@Override
          ???public?void?setApplicationContext(ApplicationContext applicationContext)?throws?BeansException {
          ???????System.out.println("我保存了Spring上下文");
          ???????applicationContext = applicationContext;
          ??}
          }


          總結(jié):

          解決if-else的思路就是使用策略模式,針對不同“狀態(tài)”的訂單,使用不同的類來處理邏輯,這樣就可以很好地進行了“解耦”操作。但是,如果新增一個“狀態(tài)表示 ”,我們就要在主邏輯處添加if-else進行判斷要用哪個類來處理。

          而解決這個“判斷 ”的中使用的if-else就有很多方法:抽象工廠也是一個不錯的方法。而我們使用Spring的控制反轉(zhuǎn)同樣也可以很好地解決這個問題。這么做的好處如下:

          1. “真正的”解決了與我們業(yè)務(wù)無關(guān)的if-else;

          2. 不用前后端再進行狀態(tài)的表示“約定”,之前用0表示“待付款”,1表示 “待發(fā)貨”這樣的操作,如果記錯,那一定會有大問題?,F(xiàn)在,使用特定的字符串來表示,也就是說,前端直接傳入想要解決這個方案對應(yīng)的bean,從而少去了“復雜且易出錯的約定”環(huán)節(jié)。

          435d61a248fe5d33f56fd72f170b3fb0.webp

          點擊“閱讀原文”獲取代碼吧

          瀏覽 36
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天操,天天干,天天日 | 色欲欲www成人网站 | 日韩人人操 | 在线观看黄色一级电影及小说 | www.苗条身,材骚气逼逼出水 |