更新時(shí)間:2018年12月07日11時(shí)46分 來(lái)源:傳智播客 瀏覽次數(shù):
# 設(shè)計(jì)模式-責(zé)任鏈
## 定義
? 責(zé)任鏈模式(Chain of Responsibility)使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接受者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有對(duì)象處理完它為止。
? 責(zé)任:當(dāng)接收者收到一個(gè)請(qǐng)求后就有責(zé)任要把這個(gè)請(qǐng)求處理完,如果它處理不了,則可以轉(zhuǎn)給其它處理者。
? 鏈:請(qǐng)求最終得到處理完成這個(gè)過(guò)程所經(jīng)歷過(guò)的每個(gè)處理者連接起來(lái)形成一條鏈。
類(lèi)型:行為類(lèi)模式
## 特點(diǎn)
1. 接收請(qǐng)求的對(duì)象連接成一條鏈,對(duì)象之間存在層級(jí)關(guān)系。
2. 這些對(duì)象可處理請(qǐng)求,也可傳遞請(qǐng)求,直到有對(duì)象處理該請(qǐng)求
## 責(zé)任鏈模式涉及到的角色
1. 抽象處理者角色(Handler):定義了處理請(qǐng)求的接口或者抽象類(lèi),提供了處理請(qǐng)求的方法(handlleRequest)和設(shè)置下一個(gè)處理者(nextHandler)的方法
2. 具體處理者角色(ConcreteHandler):實(shí)現(xiàn)或者繼承抽象這角色,具體邏輯根據(jù)實(shí)際的架構(gòu)來(lái)定
## 責(zé)任鏈模式類(lèi)圖
![class](pics\class.png)
## 實(shí)例:?jiǎn)T工晉級(jí)流程處理
### 分析
? 員工晉級(jí)流程涉及多個(gè)部門(mén)的審批。我們可以用UML的活動(dòng)圖來(lái)表示
![員工晉升流程圖](pics\員工晉升流程圖.png)
責(zé)任鏈模式是一種行為模式,因此我們可以給上圖中UML圖中所涉及到的每個(gè)處理行為都定義成一個(gè)真正的處理類(lèi)
### 代碼實(shí)現(xiàn)
#### 1. 項(xiàng)目目錄結(jié)構(gòu)
![工程目錄結(jié)構(gòu)](pics\工程目錄結(jié)構(gòu).png)
#### 2. 創(chuàng)建抽象處理者角色
Hanlder類(lèi)
```java
package com.itheima.demo.handler;
public abstract class Handler {
// 下個(gè)處理器
private Handler nextHandler;
// 處理當(dāng)下的請(qǐng)求
public abstract void handleRequest();
// 獲取下個(gè)處理器
public Handler getNextHandler() {
return nextHandler;
}
// 設(shè)置下個(gè)處理器
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}
```
#### 3. 創(chuàng)建各個(gè)具體處理者角色
* 員工發(fā)起晉級(jí)申請(qǐng)?zhí)幚?/p>
```java
package com.itheima.demo.handler;
/**
* 員工晉升申請(qǐng)
*
*/
public class EmpRequestPromotionHandler extends Handler {
/**
* 處理提交晉升申請(qǐng)
*/
@Override
public void handleRequest() {
System.out.println("員工提交晉升申請(qǐng)");
// 由下個(gè)處理者來(lái)處理
getNextHandler().handleRequest();
}
}
```
* 直屬領(lǐng)導(dǎo)的處理
```java
package com.itheima.demo.handler;
/**
* 直屬領(lǐng)導(dǎo)的處理
*
*/
public class Level1Handler extends Handler {
/**
* 直屬領(lǐng)導(dǎo)的處理: 填寫(xiě)晉升人員基本情況
*/
@Override
public void handleRequest() {
System.out.println("--直屬領(lǐng)導(dǎo)的處理: 填寫(xiě)晉升人員基本情況");
// 處理完后由下個(gè)處理者處理
getNextHandler().handleRequest();
}
}
```
* 部門(mén)總監(jiān)的處理
```java
package com.itheima.demo.handler;
/**
* 部門(mén)總監(jiān)的處理
*
*/
public class Level2Handler extends Handler {
/**
* 部門(mén)總監(jiān)的處理: 填寫(xiě)晉升人員基本情況
*/
@Override
public void handleRequest() {
System.out.println("----部門(mén)總監(jiān)的處理: 進(jìn)入能力業(yè)績(jī)考核");
int random = (int)(Math.random() * 10);
if(random < 9) {
System.out.println("----考核通過(guò)");
// 交給下個(gè)處理者處理
getNextHandler().handleRequest();
}else {
System.out.println("----考核沒(méi)通過(guò)");
System.out.println("流程結(jié)束");
}
}
}
```
* 執(zhí)行總裁的處理
```java
package com.itheima.demo.handler;
/**
* 執(zhí)行總裁的處理
*
*/
public class Level3Handler extends Handler {
/**
* 根據(jù)組織架構(gòu)判定是否晉升
*/
@Override
public void handleRequest() {
System.out.println("------執(zhí)行總裁的處理:根據(jù)組織架構(gòu)判定是否晉升");
int random = (int)(Math.random() * 10);
if(random < 9) {
System.out.println("------審批通過(guò)");
// 考核通過(guò),交給下個(gè)處理者處理
getNextHandler().handleRequest();
}else {
System.out.println("------審批沒(méi)通過(guò)");
System.out.println("流程結(jié)束");
}
}
}
```
* 人事部的處理
```java
package com.itheima.demo.handler;
/**
* 人事部的處理
*/
public class HR1Handler extends Handler {
/**
* 是否符合晉升標(biāo)準(zhǔn)
*/
@Override
public void handleRequest() {
System.out.println("--------人事部的處理: 是否符合晉升標(biāo)準(zhǔn)");
int random = (int)(Math.random() * 10);
if(random < 9) {
System.out.println("--------審批通過(guò)");
// 考核通過(guò),交給下個(gè)處理者處理
getNextHandler().handleRequest();
}else {
System.out.println("--------審批沒(méi)通過(guò)");
System.out.println("流程結(jié)束");
}
}
}
```
* 人事總裁的處理
```java
package com.itheima.demo.handler;
/**
* 人事總裁的處理
*/
public class HR2Handler extends Handler {
/**
* 是否符合晉升標(biāo)準(zhǔn)審批
*/
@Override
public void handleRequest() {
System.out.println("----------人事總裁的處理: 是否符合晉升標(biāo)準(zhǔn)審批");
int random = (int)(Math.random() * 10);
if(random < 9) {
System.out.println("----------審批通過(guò)");
// 考核通過(guò),交給下個(gè)處理者處理
getNextHandler().handleRequest();
}else {
System.out.println("----------審批沒(méi)通過(guò)");
System.out.println("流程結(jié)束");
}
}
}
```
* 人事部通知處理
```java
package com.itheima.demo.handler;
/**
* 人事部的處理2
*/
public class HRAdviceHandler extends Handler {
/**
* 通知晉升處理
*/
@Override
public void handleRequest() {
System.out.println("--------------人事部的處理2:通知晉升人員確認(rèn)");
// 處理完后由下個(gè)處理者處理
getNextHandler().handleRequest();
}
}
```
* 員工簽名的處理
```java
package com.itheima.demo.handler;
/**
* 員工簽名的處理
*/
public class EmpSignUpHandler extends Handler {
/**
* 員工簽名的處理
*/
@Override
public void handleRequest() {
System.out.println("----------------員工的處理2:簽字確認(rèn)");
// 處理完后由下個(gè)處理者處理
getNextHandler().handleRequest();
}
}
```
* 人事部通告與歸檔的處理
```java
package com.itheima.demo.handler;
/**
* 人事部通告與歸檔的處理
*/
public class HRAnnouncementHandler extends Handler {
/**
* 通告與歸檔
*/
@Override
public void handleRequest() {
System.out.println("------------------人事部的處理3:通告與歸檔");
System.out.println("全部流程走完");
}
}
```
#### 4. 創(chuàng)建調(diào)用類(lèi)
```java
package com.itheima.demo;
import com.itheima.demo.handler.EmpRequestPromotionHandler;
import com.itheima.demo.handler.EmpSignUpHandler;
import com.itheima.demo.handler.HR1Handler;
import com.itheima.demo.handler.HR2Handler;
import com.itheima.demo.handler.HRAdviceHandler;
import com.itheima.demo.handler.HRAnnouncementHandler;
import com.itheima.demo.handler.Handler;
import com.itheima.demo.handler.Level1Handler;
import com.itheima.demo.handler.Level2Handler;
import com.itheima.demo.handler.Level3Handler;
public class Client {
public static void main(String[] args) {
// 構(gòu)建每個(gè)行為的處理器
Handler empHandler = new EmpRequestPromotionHandler();
Handler level1Handler = new Level1Handler();
Handler level2Handler = new Level2Handler();
Handler level3Handler = new Level3Handler();
Handler hr1Handler = new HR1Handler();
Handler hr2Handler = new HR2Handler();
Handler hrAdviceHandler = new HRAdviceHandler();
Handler empSignUpHandler = new EmpSignUpHandler();
Handler hrAnnouncementHandler = new HRAnnouncementHandler();
// 設(shè)置每個(gè)處理的下個(gè)處理器
empHandler.setNextHandler(level1Handler);
level1Handler.setNextHandler(level2Handler);
level2Handler.setNextHandler(level3Handler);
level3Handler.setNextHandler(hr1Handler);
hr1Handler.setNextHandler(hr2Handler);
hr2Handler.setNextHandler(hrAdviceHandler);
hrAdviceHandler.setNextHandler(empSignUpHandler);
empSignUpHandler.setNextHandler(hrAnnouncementHandler);
// 員工發(fā)起晉級(jí)申請(qǐng)
empHandler.handleRequest();
}
}
```
#### 5. 運(yùn)行效果
![result](pics\result.png)
## 總結(jié)
? 責(zé)任鏈模式通過(guò)建立一條鏈來(lái)組織請(qǐng)求的處理者,請(qǐng)求將沿著鏈進(jìn)行傳遞,而請(qǐng)求發(fā)送者無(wú)須知道請(qǐng)求在何時(shí)、何處以及如何被處理,實(shí)現(xiàn)了請(qǐng)求發(fā)送者與處理者的解耦。在實(shí)際軟件開(kāi)發(fā)中,如果遇到有多個(gè)對(duì)象可以處理同一請(qǐng)求時(shí)可以考慮使用職責(zé)鏈模式,一般都可以用來(lái)保證請(qǐng)求得到最終的執(zhí)行。
北京校區(qū)