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

設(shè)計模式之責任鏈模式

開發(fā) 前端
給多個對象處理請求的機會,減少請求的發(fā)送者與接受者之間的耦合。將接受對象鏈接起來,在鏈中傳遞請求,直到有一個對象處理這個請求。

[[441814]]

簡介

定義:給多個對象處理請求的機會,減少請求的發(fā)送者與接受者之間的耦合。將接受對象鏈接起來,在鏈中傳遞請求,直到有一個對象處理這個請求。 

速記:責任傳遞 

案例:財務(wù)報銷、擊鼓傳花、Sentinel(CtSph.java)、Zookeeper、Nacos

我考慮對創(chuàng)建訂單的流程通過責任鏈模式的方式進行重構(gòu),先來看看我創(chuàng)建訂單的流程。

創(chuàng)建訂單 -> 消耗優(yōu)惠券 -> 發(fā)貨 -> 返利

環(huán)境介紹:

jdk 1.8 , spring 5.2.x

代碼實現(xiàn)

代碼實現(xiàn)如下圖所示,通過 AbstractOrderHandler 定義抽象的接口,規(guī)范 Handler 的行為,在我的場景下有 4 個 Handler : 1、CreateOrderHandler 創(chuàng)建訂單。2、UseCouponOrderHandler 使用優(yōu)惠券 3、GoodsDeliverOrderHandler 商品發(fā)貨 4、RebateOrderHandler 營銷返現(xiàn) 通過這樣的設(shè)計我們就可以巧妙的,將繁雜的流程,進行水平拆分為 Handler ,將之前的 BIG Method ,拆分成了一個可以復用的低耦合的類文件。下面是一個類的示意圖:

定義抽象方法

AbstractOrderHandler 定義如下,主要是有兩個作用,定義 doHandle 抽象方法,以及為后期按照類型區(qū)分 Handler 業(yè)務(wù)的的 getTypeEnum 方法。

  1. public abstract class AbstractOrderHandler { 
  2.  
  3.     /** 
  4.      * 區(qū)分類型 
  5.      * 
  6.      * @return 
  7.      */ 
  8.     protected abstract OrderTypeEnum getTypeEnum(); 
  9.  
  10.     /** 
  11.      * 核心處理 
  12.      * 
  13.      * @param context 上下文 
  14.      * @param args    拓展參數(shù) 
  15.      */ 
  16.     public void doHandle(OrderHandleContext context, 
  17.                          OrderHandlerChain chain, Object... args) { 
  18.         // 我是否可以處理 
  19.         if (Objects.isNull(getTypeEnum()) ||  
  20.             Objects.equals(context.getTypeEnum(), getTypeEnum())) { 
  21.             // 讓我來處理 
  22.             doHandle(context, args); 
  23.         } 
  24.         // 我處理完了,交給下家 
  25.         chain.handle(context, args); 
  26.     } 
  27.  
  28.     /** 
  29.      * 具體業(yè)務(wù)處理 
  30.      * 
  31.      * @param context 
  32.      * @param args 
  33.      */ 
  34.     protected abstract void doHandle(OrderHandleContext context, Object... args); 
  35.  

責任鏈的實現(xiàn)

具體的 Handler 實現(xiàn),這里我列舉了兩個 Handler 的代碼,分別是 CreateOrderHandler 創(chuàng)建訂單、RebateOrderHandler 營銷返利。核心邏輯即使實現(xiàn) AbstractOrderHandler 接口,并且實現(xiàn)內(nèi)部的細分邏輯。

  1. // 創(chuàng)建訂單 
  2. @Slf4j 
  3. @Service 
  4. @Order(100) 
  5. public class CreateOrderHandler extends AbstractOrderHandler { 
  6.  
  7.     @Override 
  8.     protected OrderTypeEnum getTypeEnum() { 
  9.         return null
  10.     } 
  11.      
  12.     @Override 
  13.     protected void doHandle(OrderHandleContext context, Object... args) { 
  14.         log.info("default create order ... "); 
  15.  
  16.         // 鎖定庫存 
  17.         lockSku(context, args); 
  18.          
  19.         // 保存訂單 
  20.         saveOrder(context); 
  21.          
  22.         // 扣除庫存 
  23.         deductSku(context, args) 
  24.     } 
  25.  
  26.  
  27. // 訂單反現(xiàn)金 
  28. @Service 
  29. @Slf4j 
  30. @Order(200) 
  31. public class RebateOrderHandler extends AbstractOrderHandler { 
  32.  
  33.     @Override 
  34.     protected OrderTypeEnum getTypeEnum() { 
  35.         return null
  36.     } 
  37.  
  38.     @Override 
  39.     protected void doHandle(OrderHandleContext context, Object... args) { 
  40.         log.info("default rebate order ... "); 
  41.     } 

定義調(diào)用入口

OrderHandlerChain 是外部調(diào)用的入口,其實它主要的作用就是獲取 AbstractOrderHandler 并且排序(即串聯(lián)/編排 Handler ) 然后進行執(zhí)行。這里我充分使用了 Spring 的 Bean 排序功能,通過在 Handler 上面定義 @Order 注解并且傳入順序值,我們在 @Autowired 獲取 List 的時候,Spring 會給我自動注入排好序的 handlerList 。

  1. @Slf4j 
  2. @Component 
  3. public class OrderHandlerChain { 
  4.  
  5.     @Autowired 
  6.     private List<AbstractOrderHandler> chain; 
  7.     @Autowired 
  8.     private ApplicationContext applicationContext; 
  9.  
  10.     public void handle(OrderHandleContext context, Object... objects) { 
  11.         if (context.getPos() < chain.size()) { 
  12.             AbstractOrderHandler handler = chain.get(context.getPos()); 
  13.             // 移動位于處理器鏈中的位置 
  14.             context.setPos(context.getPos() + 1); 
  15.             handler.doHandle(context, this, objects); 
  16.         } 
  17.     } 
  18.  

業(yè)務(wù)拓展

如果我的訂單邏輯發(fā)生變化,需要支持汽車訂單的創(chuàng)建和兼容。我們可以增加 Car 處理的 handler 通過指定不同 OrderTypeEnum 進行處理,如果你不想創(chuàng)建更多的 handler 類文件也可以通過 @Bean 來進行實現(xiàn)。

這里其實也是一種妥協(xié)的方式,其實和直接實現(xiàn) AbstractOrderHandler 并沒有什么區(qū)別,都會生成 .class 文件,只是說在開發(fā)側(cè)來看少了一個 Java 文件而已,也會占 JVM 的 Metaspace 空間。

如下所示:

  1. @Configuration 
  2. public class CarOrderHandlers { 
  3.  
  4.     /** 
  5.      * 汽車訂單創(chuàng)建 
  6.      * 
  7.      * @return 
  8.      */ 
  9.     @Bean(name = "createOrderByCar"
  10.     public AbstractOrderHandler createOrderByCar() { 
  11.         return new CreateOrderHandler() { 
  12.             @Override 
  13.             protected OrderTypeEnum getTypeEnum() { 
  14.                 return OrderTypeEnum.Car; 
  15.             } 
  16.  
  17.             @Autowired 
  18.             private ApplicationContext applicationContext; 
  19.  
  20.             @Override 
  21.             protected void doHandle(OrderHandleContext context, Object... args) { 
  22.                 System.out.println("car order create ...."); 
  23.             } 
  24.         }; 
  25.     } 
  26.  

測試代碼

測試代碼如下,我們只需要傳入一個 Context 對象然后調(diào)用 chain.handle 方法即可。

  1. @Slf4j 
  2. @SpringBootTest(classes = App.class) 
  3. public class OrderHandlerChainTest { 
  4.  
  5.     @Resource 
  6.     private OrderHandlerChain chain; 
  7.  
  8.     @Test 
  9.     public void testOrderChain() { 
  10.  
  11.         OrderHandleContext context = new OrderHandleContext(); 
  12.         context.setTypeEnum(OrderTypeEnum.Car); 
  13.         chain.handle(context, null); 
  14.     } 

總結(jié)

本文主要是利用了 Spring 進行排序, Bean 定義等特征,實現(xiàn)責任鏈。感覺改造過后,有一點策略 + 模板 的感覺。策略模式主要是運用: 多方案切換的場景對業(yè)務(wù)進行垂直路由分別處理。責任鏈模式主要運用:責任傳遞的場景對業(yè)務(wù)進行水平分段處理粒度可以說更加細一些。

其實我們 JDK8 還提供了 @FunctionalInterface 函數(shù)接口,我們也可以將 AbstractOrderHandler 修改為 interface 接口,這樣我們就可以通過 lambda 表達式的方式注冊 Handler 其實本質(zhì)都是一樣的。Over!歡迎大家留言交流。

參考文章

https://www.cnblogs.com/vcmq/p/12542399.html

http://c.biancheng.net/view/1383.html

 

責任編輯:武曉燕 來源: 運維開發(fā)故事
相關(guān)推薦

2010-04-01 09:10:03

PHP設(shè)計模式責任鏈模式

2012-03-28 13:28:56

Java設(shè)計模式

2023-06-05 07:55:31

2024-01-30 13:15:00

設(shè)計模式責任鏈

2020-11-17 09:32:57

設(shè)計模式責任鏈

2023-09-26 00:27:07

設(shè)計模式鏈接

2022-12-28 08:08:57

2021-08-14 08:17:49

Android設(shè)計模式OKHttp

2022-11-01 08:46:20

責任鏈模式對象

2024-05-09 12:17:00

責任鏈設(shè)計模式

2024-06-04 13:11:52

Python行為設(shè)計模式開發(fā)

2024-12-03 15:52:45

責任鏈Java

2021-07-14 10:08:30

責任鏈模式加工鏈

2021-06-05 17:59:00

責任鏈模式設(shè)計

2023-09-28 08:45:56

開源責任鏈模式

2020-08-21 07:23:50

工廠模式設(shè)計

2021-05-25 09:00:52

責任鏈模式設(shè)計模式面試經(jīng)歷

2015-09-08 13:39:10

JavaScript設(shè)計模式

2012-01-13 15:59:07

2023-09-04 13:14:00

裝飾器設(shè)計模式
點贊
收藏

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