0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

什么是責任鏈?

汽車電子技術 ? 來源:程序猿知秋 ? 作者: 程序猿知秋 ? 2023-02-16 14:41 ? 次閱讀

什么是責任鏈?

責任鏈模式是行為模式的一種,它將需要觸發(fā)的Handler組成一條鏈,發(fā)送者將請求發(fā)給鏈的第一個接收者,并且沿著這條鏈傳遞,直到有一個Handler來處理它或者直到最后也沒有對象處理而留在鏈末尾端;責任連模式的重點是在鏈上,由一條鏈去處理相似的請求,在鏈中決定誰來處理這個請求

責任鏈分為純責任鏈與不純責任鏈(一般實戰(zhàn)應用較多)

**純職責鏈 **

1.每個處理者接收到請求后,要么單純轉發(fā)請求,要么單純處理請求。不允許既處理請求,又轉發(fā)請求的情況。

2.請求必須被責任鏈上的某個處理者處理。不允許出現(xiàn)請求未被處理的情況。

**不純職責鏈 **

1.每個處理者接收到請求后,除了單純轉發(fā)請求,或者單純處理請求,還可以部分處理請求后,轉發(fā)。

2.請求可以不被責任鏈上的任何處理者處理。

責任鏈優(yōu)點

1.解耦請求者和處理者。

2.非常靈活,可以任意組裝

3.各個節(jié)點的責任明確

缺點

1.每次都是從鏈頭開始。

2. 可能造成死循環(huán)。責任鏈如果是環(huán)狀的,可能會導致循環(huán)調用,造成死循環(huán)。

純責任鏈的代碼Demo:

/**
     * 在公司OA系統(tǒng)請假審批流程
如果請假小于3天只需要項目經(jīng)理批復就行;
如果請假大于等于3天,小于7天需要人事經(jīng)理批復了;
如果請假大于等于7天,小于15天需要總經(jīng)理批復了;
如果申請請假大于等于15天,決絕批復......
     * @param args
     */
 public static void main(String[] args) {
        Leader manager = new Manager("張三");
        Leader hrManager = new HrManager("李四");
        Leader generalManager = new GeneralManager("王麻子");


        //組織責任鏈對象的關系
        manager.setNextLeader(hrManager);
        hrManager.setNextLeader(generalManager);
        //請假
        LeaveRequest request = new LeaveRequest("parry", 10, "回家相親!");
        manager.dealLeaveRequest(request);
  }

public abstract class Leader {
    // 領導姓名
    protected String name;
    // 責任鏈上的后繼對象
    protected Leader nextLeader;
    public Leader(String name) {
        super();
        this.name = name;
    }


    public void setNextLeader(Leader nextLeader) {
        this.nextLeader = nextLeader;
    }

    public abstract void dealLeaveRequest(LeaveRequest request);
}

  public class HrManager extends Leader{
      public HrManager(String name) {
          super(name);
      }


      @Override
      public void dealLeaveRequest(LeaveRequest request) {
        if (3 <= request.getLeaveDay() && request.getLeaveDay() < 7) {
            System.out.println("人事經(jīng)理:" + name + " 審批了 " + request.getEmployee() + "請假" + request.getLeaveDay()
                    + "天的請求,請假原因:" + request.getReason());
        } else {
            if (this.nextLeader != null) {
                this.nextLeader.dealLeaveRequest(request);
            }
        }
    }
}


public class GeneralManager extends Leader {
    public GeneralManager(String name) {
        super(name);
    }


    @Override
    public void dealLeaveRequest(LeaveRequest request) {
        if (7 <= request.getLeaveDay() && request.getLeaveDay() <= 15) {
            System.out.println("總經(jīng)理:" + name + " 審批了 " + request.getEmployee() + "請假" + request.getLeaveDay()
                    + "天的請求,請假原因:" + request.getReason());
        } else {
            System.out.println(
                    "總經(jīng)理:" + name + " 拒絕了 " + request.getEmployee() + "請假" + request.getLeaveDay() + "天的請求,請假不能超過15天");
        }
    }
}


public class Manager extends Leader{
    public Manager(String name) {
        super(name);
    }


    @Override
    public void dealLeaveRequest(LeaveRequest request) {
        if (request.getLeaveDay() < 3) {
            System.out.println("經(jīng)理:" + name + " 審批了 " + request.getEmployee() + "請假" + request.getLeaveDay()
                    + "天的請求,請假原因:" + request.getReason());
        } else {
            if (this.nextLeader != null) {
                this.nextLeader.dealLeaveRequest(request);
            }
        }
    }
}


@Data
public class LeaveRequest {
   //姓名
    private String name;
   //請假天數(shù)
    private int leaveDay;
    //請假原因
    private String reason;


    public LeaveRequest(String name, int leaveDay, String reason) {
        this.name=name;
        this.leaveDay=leaveDay;
        this.reason=reason;
    }  
}

電商售后使用責任鏈(不純責任鏈)

售后業(yè)務梳理

電商售后常見三種模式:

僅退款、退款退貨、退款換貨

售后業(yè)務可分為

僅退款: 采購商申請——>商家審核——>完成

退款退貨:采購商申請——>商家審核——>采購商發(fā)貨——>商家確認收貨——>完成

退款換貨:采購商申請——>商家審核——>采購商發(fā)貨——>商家確認收貨——>商家發(fā)出新品——>采購商確認收貨——>完成

僅退款的實際退款等操作在商家審核時,而退款退貨和退款換貨則在確認收貨時。

以下為售后責任鏈流程:

售后->校驗退款單狀態(tài)->原路退款(以下單支付方式為準)->退積分或其它優(yōu)惠->更新訂單及對應商品退款信息->保存結算->保存財務流水->保存/更新退款日志->發(fā)送退款成功異步消息

三種售后的核心退款業(yè)務流程基本是一致的,少個別節(jié)點業(yè)務邏輯有所區(qū)別,將核心業(yè)務抽成責任鏈的各個節(jié)點,這對售后來說,代碼的復用性提高了很多,同時業(yè)務處理更加清晰,犯錯率大大降低。

以下為售后中代碼使用Demo

定義一個節(jié)點的基類接口

public interface BaseRefundHandler {
    void handle(PipelineContext context); 
}

售后責任鏈組裝,以下以僅退款為例

public class RefundPipeBean {
/**
 * 僅退款,責任鏈初始化節(jié)點
 */
public List<String> refundPipe = new ArrayList<>();


  public List<String> getRefundPipe() {
      refundPipe.add("checkRefundStatus"); //校驗退款單狀態(tài)
      refundPipe.add("refundMoney");  //原路退款(獲取訂單支付方式)
      refundPipe.add("returnScore");  //退積分或其它優(yōu)惠券類
       ......
      return refundPipe;
  }


  @Bean
  @Scope("prototype")
  public CheckRefundStatus checkRefundStatus() {return new CheckRefundStatus();}

  @Bean
  @Scope("prototype")
  public RefundMoney refundMoney() {return new RefundMoney();}
  ......
}

** 注: 這個配置就等同于之前在xml里的配置**

"checkRefundStatus" class="com.xx.CheckRefundStatus"/>

創(chuàng)建一個啟動監(jiān)聽器

@Component
public class RefundPipeListener extends ApplicationObjectSupport implements InitializingBean {
    private static Map<String, List> handlersMap = new HashMap<>();
     
   public static Map<String, List> getHandlersMap() {
        return handlersMap;
    }

    //最好定義成全局的,此處因演示 才在類中寫 。 責任鏈的名稱
   public static String ONLY_REFUND="ONLY_REFUND";
  @Override
  public void afterPropertiesSet() throws Exception {
    RefundPipeBean refundPipeBean=new RefundPipeBean();
     //裝載退款業(yè)務鏈.....
    List normalHandlers=new ArrayList<>();

    for (String s : refundPipeBean.getRefundPipe()) {
        BaseRefundHandler normalHandler = (BaseRefundHandler) getApplicationContext().getBean(s);
        normalHandlers.add(normalHandler);
        handlersMap.put(ONLY_REFUND, normalHandlers);
    } 
  }
}

創(chuàng)建節(jié)點傳遞對象所用POJO類

@Data
public class PipelineContext<K, V> extends ConcurrentHashMap<K, V> {
    protected boolean success = false;
    //責任鏈結束標識
    protected boolean isEnd = false;
    protected String resultCode;
    private  Object data;


    public boolean isSuccess() {
        return success;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }


    public boolean isEnd() {
        return isEnd;
    }


    public void setEnd(boolean end) {
        isEnd = end;
    }
}


public class RefundPipelineContext<K, V> extends PipelineContext<K, V> {
    /**
     * 封裝退款單信息
    */
    private RefundInfoPipeVo refundInfoPipeVo;


    public RefundInfoPipeVo getRefundInfoPipeVo() {
        return refundInfoPipeVo;
    }


    public void setRefundInfoPipeVo(RefundInfoPipeVo refundInfoPipeVo) {
        this.refundInfoPipeVo = refundInfoPipeVo;
    }
}

創(chuàng)建節(jié)點

public class CheckRefundStatus implements BaseRefundHandler {
  @Override
  public void handle(PipelineContext<String, RefundInfoPipeVo> context) {
     //業(yè)務邏輯 todo
     ......
   //表示該節(jié)點運行正常,可以繼續(xù)向下走
   context.setSuccess(true);
  }
}

業(yè)務調用層

@RestController
public class RefundInfoController {
  @Autowired
  RefundInfoService refundInfoService;

  @ApiOperation("僅退款")
  @RequestMapping(value = "/auditRefund", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=UTF-8")
  public RespData<Boolean> auditRefund(xxx) {
      refundInfoService.auditRefund(xxx);
      return RespData.success("審核成功",true);
  }
}


public interface RefundInfoService {
  void auditRefund(xxx);
}


@Service("refundInfoService")
public class RefundInfoServiceImpl implements RefundInfoService {


    @Override
    public void auditRefund(xxx) {
        //業(yè)務邏輯 todo 
        RefundInfoResultVo refundInfoResultVo = refundInfoMapper.queryById(platformId, refundId);
        ......
        PipelineContext<String, RefundInfoPipeVo> refund = new RefundPipelineContext<>();
        //在責任鏈中傳遞參數(shù)對象
        refund.put("refund", refundInfoResultVo);
        Map<String, List> map = RefundPipelineChangeListener.getHandlersMap();
        //通過責任鏈的名稱獲取對應鏈 。 此處key值應為一個全局的常量,與上面監(jiān)聽器中的鏈條名一致
        List baseRefundHandlers = map .get(ONLY_REFUND); 
        for (BaseRefundHandler handler : baseRefundHandlers) {
            handler.handle(refund);
            if (refund.isEnd()) {
                System.out.println("責任鏈執(zhí)行結束...");
                break;
            }
            if (!refund.isSuccess()) {
                        System.out.println("責任鏈執(zhí)行失敗...");
                break;
            }
        }
    }
}

整體總結

以上是責任鏈在業(yè)務中創(chuàng)建及使用的流程。

同時以上流程也還存在一些可優(yōu)化點:

  1. 責任鏈節(jié)點硬編碼問題
  2. 添加同步事務控制
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 模式
    +關注

    關注

    0

    文章

    65

    瀏覽量

    13357
  • handler
    +關注

    關注

    0

    文章

    7

    瀏覽量

    3017
收藏 人收藏

    評論

    相關推薦

    Spring高級49講-060-模擬實現(xiàn)調用-責任模式

    spring
    電子學習
    發(fā)布于 :2023年01月07日 17:55:22

    基于ArkUI框架開發(fā)-ImageKnife渲染層重構

    的實現(xiàn),都采用了責任模式,提高了自定義繪制擴展能力。將部分通用方法封裝成工廠方法,減少開發(fā)者代碼量。通用方法從配置參數(shù)剝離,可采用鏈式調用方式使用這些方法。為了支持列表ImageKnifeOption
    發(fā)表于 04-06 10:01

    電子行業(yè)供應責任向前邁出一步

    電子行業(yè)供應責任向前邁出一步     瑞士蒙特勒2010年3月11日電 /美通社亞洲/ -- Achilles Information Ltd. 與 Global e-Sustainability Initiati
    發(fā)表于 03-11 18:19 ?450次閱讀

    5G時代的關鍵安全特征介紹

    同時,云計算也在推動業(yè)務的發(fā)展,讓供應責任日益的復雜。使用電信的運營商各式各樣的豐富的服務的同時,也帶來了挑戰(zhàn)。其解決之道是通過API來提供,保證設計的安全。Jon France指出,“這不
    發(fā)表于 05-09 09:14 ?1662次閱讀

    精通Python設計模式的PDF電子書免費下載

    本書分三部分、共 16 章,介紹一些常用的設計模式。第一部分介紹處理對象創(chuàng)建的設計模式,包括工廠模式、建造者模式、原型模式;第二部分介紹處理一個系統(tǒng)中不同實體(類、對象等)之間關系的設計模式,包括外觀模式、享元模式等 ;第三部分介紹處理系統(tǒng)實體之間通信的設計模式,包括責任
    發(fā)表于 06-13 08:00 ?9次下載

    FCA加入RSBN合作項目,為電動汽車建立負責任的鋰離子電池供應

    據(jù)外媒報道,當?shù)貢r間12月10日,F(xiàn)CA宣布加入負責任采購區(qū)塊網(wǎng)絡(Responsible Sourcing Blockchain Network,RSBN),后者是一個合作項目,主要利用區(qū)塊技術,實現(xiàn)從礦場到市場的可持續(xù)、
    的頭像 發(fā)表于 12-12 17:01 ?3788次閱讀

    C語言設計模式的程序資料合集

    之模板模式,C語言設計模式之工廠模式,C語言設計模式之責任模式,C語言設計模式之抽象工廠模式,C語言設計模式之狀態(tài)模式。
    發(fā)表于 11-16 08:00 ?4次下載

    一起看看責任設計模式吧!

    如何解決這個問題,我們可以通過鏈表將每一關連接起來,形成責任的方式,第一關通過后是第二關,第二關通過后是第三關 ....,這樣客戶端就不需要進行多重 if 的判斷了
    的頭像 發(fā)表于 07-08 16:25 ?810次閱讀

    如何用責任默認優(yōu)雅地進行參數(shù)校驗

    那么有什么更好的參數(shù)校驗的方式呢?本文就推薦一種通過責任設計模式來優(yōu)雅地實現(xiàn)參數(shù)的校驗功能,我們通過一個用戶注冊的例子來講明白如何實現(xiàn)。
    的頭像 發(fā)表于 04-06 15:00 ?419次閱讀

    責任設計模式詳解

    責任模式是一種行為設計模式, 允許你將請求沿著處理者進行發(fā)送。收到請求后, 每個處理者均可對請求進行處理, 或將其傳遞給上的下個處理者。
    的頭像 發(fā)表于 05-22 15:12 ?394次閱讀
    <b class='flag-5'>責任</b><b class='flag-5'>鏈</b>設計模式詳解

    設計模式行為型:責任模式

    將請求發(fā)送者和請求接受者解耦,讓請求的接受者形成鏈式操作,所有人都能夠接受接受到請求,直到有人處理請求。
    的頭像 發(fā)表于 06-06 17:33 ?736次閱讀
    設計模式行為型:<b class='flag-5'>責任</b><b class='flag-5'>鏈</b>模式

    AMD借助創(chuàng)新與合作推進企業(yè)責任

    、數(shù)字化影響、供應責任,以及多元化、歸屬感和包容性等方面取得的進展。AMD已連續(xù)28年發(fā)布其企業(yè)責任項目及計劃,今年的報告首次包含近期收購公司的環(huán)境和社會數(shù)據(jù)。 AMD企業(yè)責任與國際
    的頭像 發(fā)表于 08-25 12:58 ?308次閱讀

    AMD發(fā)布年度企業(yè)責任報告 助力解決全球最重要的挑戰(zhàn)

    ? ? AMD的節(jié)能、高性能產(chǎn)品和深度合作 助力解決全球最重要的挑戰(zhàn) AMD發(fā)布年度企業(yè)責任報告,詳細闡述了公司在環(huán)境可持續(xù)發(fā)展、數(shù)字化影響、供應責任,以及多元化、歸屬感和包容性等方面取得的進展
    的頭像 發(fā)表于 09-07 16:20 ?1023次閱讀

    設計模式之責任模式概述

    設計模式是一些被反復使用的、具有普遍性的設計解決方案,它們是在特定情境下對軟件設計問題的成功解決方式的總結和歸納。
    的頭像 發(fā)表于 09-27 09:54 ?606次閱讀
    設計模式之<b class='flag-5'>責任</b><b class='flag-5'>鏈</b>模式概述

    還在自己實現(xiàn)責任?我建議你造輪子之前先看看這個開源項目

    1. 前言 設計模式在軟件開發(fā)中被廣泛使用。通過使用設計模式,開發(fā)人員可以更加高效地開發(fā)出高質量的軟件系統(tǒng),提高代碼的可讀性、可維護性和可擴展性。 責任模式是一種常用的行為型設計模式,它將請求沿著
    的頭像 發(fā)表于 09-20 14:38 ?238次閱讀
    還在自己實現(xiàn)<b class='flag-5'>責任</b><b class='flag-5'>鏈</b>?我建議你造輪子之前先看看這個開源項目