責(zé)任鏈模式是一種行為設(shè)計(jì)模式, 允許你將請(qǐng)求沿著處理者鏈進(jìn)行發(fā)送。收到請(qǐng)求后, 每個(gè)處理者均可對(duì)請(qǐng)求進(jìn)行處理, 或?qū)⑵鋫鬟f給鏈上的下個(gè)處理者。
我的理解就是:用來處理一系列的流程,一步一步地往下走,每一步就是一個(gè)責(zé)任節(jié)點(diǎn)。
使用場(chǎng)景:1、流程審批 2、權(quán)限控制
適用的場(chǎng)景很多很多,個(gè)人感覺只要是步驟多的場(chǎng)景都可以使用,本文例子采用了流程審批的場(chǎng)景。
一、簡單責(zé)任鏈實(shí)例
package designmode.responsibilitychainmode.simple;
/**
* 審批處理器
* @author pcf
* @date 2023/3/13 9:47
*/
abstract class AbstractHandler {
// 下一個(gè)審批節(jié)點(diǎn)
private AbstractHandler nextHandler;
// 設(shè)置下一個(gè)審批節(jié)點(diǎn)
public void setNextHandler(AbstractHandler nextHandler) {
this.nextHandler = nextHandler;
}
public AbstractHandler getNextHandler() {
return nextHandler;
}
// 審批
public abstract void handler();
}
class FirstHandler extends AbstractHandler {
@Override
public void handler() {
int random = (int)(Math.random()*100);
// 隨機(jī)模擬審批通過或不通過之后的流程走向
if (random % 2 == 0) {
System.out.println("組長已審批");
if (getNextHandler() != null) {
// 處理完成,審批單傳遞給下一步處理人
getNextHandler().handler();
}
} else {
System.out.println("組長不同意,說要加班");
System.out.println("審批不通過,責(zé)任鏈斷掉,審批流不再繼續(xù)向下進(jìn)行");
}
}
}
class SecHandler extends AbstractHandler {
@Override
public void handler() {
System.out.println("項(xiàng)目經(jīng)理已審批");
if (getNextHandler() != null) {
// 處理完成,審批單傳遞給下一步處理人
getNextHandler().handler();
}
}
}
class ThirdHandler extends AbstractHandler {
@Override
public void handler() {
System.out.println("行政部已審批,審批流程完畢,回家結(jié)婚去吧!");
if (getNextHandler() != null) {
// 處理完成,審批單傳遞給下一步處理人
getNextHandler().handler();
}
}
}
使用責(zé)任鏈
package designmode.responsibilitychainmode.simple;
import org.junit.Test;
/**
* @author pcf
* @date 2023/3/13 10:44
*/
public class TestRes {
@Test
public void testRes() {
System.out.println("我想要請(qǐng)假結(jié)婚!");
FirstHandler firstHandler = new FirstHandler(); // 第一個(gè)審批人
SecHandler secHandler = new SecHandler(); // 第二個(gè)審批人
ThirdHandler thirdHandler = new ThirdHandler(); // 第三個(gè)審批人
firstHandler.setNextHandler(secHandler); // 第一個(gè)審批人的后續(xù)處理人是第二個(gè)審批人
secHandler.setNextHandler(thirdHandler); // 第二個(gè)審批人的后續(xù)處理人是第三個(gè)審批人,審批鏈完成
firstHandler.handler(); // 開始審批
}
}
結(jié)果分析:
1、審批鏈(責(zé)任鏈)審批成功結(jié)果:
我想要請(qǐng)假結(jié)婚!
組長已審批
項(xiàng)目經(jīng)理已審批
行政部已審批,審批流程完畢,回家結(jié)婚去吧!
2、審批鏈(責(zé)任鏈)審批不通過結(jié)果:
我想要請(qǐng)假結(jié)婚!
組長不同意,說要加班
審批不通過,責(zé)任鏈斷掉,審批流不再繼續(xù)向下進(jìn)行
可以看FirstHandler類中的處理邏輯,如果本步審批成功,會(huì)向下一步發(fā)起流程審批。
如果本步審批失敗,則審批鏈斷掉,結(jié)束。
看完實(shí)例,責(zé)任鏈還是很好理解的。每個(gè)責(zé)任節(jié)點(diǎn)包含有它下一個(gè)責(zé)任節(jié)點(diǎn)的引用,處理完一個(gè)責(zé)任節(jié)點(diǎn)的業(yè)務(wù)后,繼續(xù)進(jìn)入向下一個(gè)責(zé)任節(jié)點(diǎn),直到最后一個(gè)節(jié)點(diǎn)。
實(shí)現(xiàn)起來還是很啰嗦的,因?yàn)樾枰獙?duì)每一個(gè)責(zé)任節(jié)點(diǎn)創(chuàng)建該節(jié)點(diǎn)的處理器,再把后面節(jié)點(diǎn)的引用賦給前一個(gè)節(jié)點(diǎn)。顯得代碼很冗余,還很不好看。
因此可以一些方法將這個(gè)組合責(zé)任鏈的過程優(yōu)化一下,最好是能夠動(dòng)態(tài)生成,可手動(dòng)配置。這樣一來針對(duì)不同的業(yè)務(wù)需要,組裝不同的責(zé)任鏈。
二、利用枚舉動(dòng)態(tài)組裝責(zé)任鏈
package designmode.responsibilitychainmode.resfactory;
/**
* 審批處理器
* @author pcf
* @date 2023/3/13 9:47
*/
abstract class AbstractHandler {
// 下一個(gè)審批節(jié)點(diǎn)
private AbstractHandler nextHandler;
// 設(shè)置下一個(gè)審批節(jié)點(diǎn)
public void setNextHandler(AbstractHandler nextHandler) {
this.nextHandler = nextHandler;
}
public AbstractHandler getNextHandler() {
return nextHandler;
}
// 審批
public abstract void handler();
}
package designmode.responsibilitychainmode.resfactory;
/**
* 組長審批
*/
public class HeadmanHandler extends AbstractHandler {
@Override
public void handler() {
int random = (int)(Math.random()*100);
// 隨機(jī)模擬審批通過或不通過之后的流程走向
if (random % 2 == 0) {
System.out.println("組長已審批");
if (getNextHandler() != null) {
// 處理完成,審批單傳遞給下一步處理人
getNextHandler().handler();
}
} else {
System.out.println("組長不同意,說要加班");
System.out.println("審批不通過,責(zé)任鏈斷掉,審批流不再繼續(xù)向下進(jìn)行");
}
}
}
package designmode.responsibilitychainmode.resfactory;
/**
* 行政部審批
*/
class ManagerHandler extends AbstractHandler {
@Override
public void handler() {
System.out.println("項(xiàng)目經(jīng)理已審批");
if (getNextHandler() != null) {
// 處理完成,審批單傳遞給下一步處理人
getNextHandler().handler();
}
}
}
package designmode.responsibilitychainmode.resfactory;
/**
* 行政部審批
*/
class HrHandler extends AbstractHandler {
@Override
public void handler() {
System.out.println("行政部已審批,審批流程完畢,回家結(jié)婚去吧!");
if (getNextHandler() != null) {
// 處理完成,審批單傳遞給下一步處理人
getNextHandler().handler();
}
}
}
package designmode.responsibilitychainmode.resfactory;
/**
* @author pcf
* @date 2023/3/13 11:31
*/
public enum ChainEnum {
HEADMAN_HANDLER(1, "designmode.responsibilitychainmode.resfactory.HeadmanHandler"),
MANAGER_HANDLER(2, "designmode.responsibilitychainmode.resfactory.ManagerHandler"),
HR_HANDLER(3, "designmode.responsibilitychainmode.resfactory.HrHandler");
private final int id;
private final String className;
ChainEnum(int id, String className) {
this.id = id;
this.className = className;
}
public int getId() {
return id;
}
public String getClassName() {
return className;
}
private static String getClassName(int id) {
for (ChainEnum enu : ChainEnum.values()) {
if (enu.getId() == id) {
return enu.getClassName();
}
}
return "";
}
// 婚嫁審批流節(jié)點(diǎn)
private static int[] weddingProcess = {1,2,3};
// 事假審批流節(jié)點(diǎn)
private static int[] thingProcess = {1,2};
// 組轉(zhuǎn)審批鏈
public static void startWeddingProcess() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
AbstractHandler[] handlers = new AbstractHandler[3];
for (int i = 0; i < weddingProcess.length; i++) {
Class<?> aClass = Class.forName(getClassName(i+1));
AbstractHandler handler = (AbstractHandler)aClass.newInstance();
handlers[i] = handler;
if (i>=1 && handlers[i - 1] != null) {
handlers[i-1].setNextHandler(handlers[i]);
}
}
handlers[0].handler();
}
}
package designmode.responsibilitychainmode.resfactory;
import org.junit.Test;
/**
* @author pcf
* @date 2023/3/13 10:44
*/
public class TestRes {
@Test
public void testRes() throws IllegalAccessException, ClassNotFoundException, InstantiationException {
System.out.println("我想要請(qǐng)假結(jié)婚!");
ChainEnum.startWeddingProcess();
}
}
// 結(jié)果
1、審批鏈(責(zé)任鏈)審批成功結(jié)果:
我想要請(qǐng)假結(jié)婚!
組長已審批
項(xiàng)目經(jīng)理已審批
行政部已審批,審批流程完畢,回家結(jié)婚去吧!
2、審批鏈(責(zé)任鏈)審批不通過結(jié)果:
我想要請(qǐng)假結(jié)婚!
組長不同意,說要加班
審批不通過,責(zé)任鏈斷掉,審批流不再繼續(xù)向下進(jìn)行