責(zé)任鏈模式(Chain of Responsibility),使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接收者之間的耦合關(guān)系。將這個對象連成一條鏈,并沿著這條鏈傳遞該請求,知道有一個對象處理它為止。
責(zé)任鏈模式的結(jié)構(gòu)圖
責(zé)任鏈模式中的角色:
- Handler:定義一個處理請示的接口
- ConcreteHandler:具體處理者類,處理它所負責(zé)的請求,可訪問它的后繼者,如果可處理該請求,就處理之,否則就將該請求轉(zhuǎn)發(fā)給它的后繼者。
責(zé)任鏈模式的簡單實現(xiàn)
(1)處理請示的接口
public class Request {
private String requestType;
private String requestContent;
private int number;
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public String getRequestContent() {
return requestContent;
}
public void setRequestContent(String requestContent) {
this.requestContent = requestContent;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
public abstract class Manager {
protected String name;
protected Manager superior;
public Manager(String name) {
this.name = name;
}
public void setSuperior(Manager superior) {
this.superior = superior;
}
public abstract void requestApplication(Request request);
}
(2)具體處理者類
public class CommonManager extends Manager {
public CommonManager(String name) {
super(name);
}
@Override
public void requestApplication(Request request) {
if (request.getRequestType().equals("請假") && request.getNumber() <= 2) {
System.out.println(name + ":" + request.getRequestContent() + "數(shù)量" + request.getNumber() + "被批準");
} else{
if (superior != null) {
superior.requestApplication(request);
}
}
}
}
public class Majordomo extends Manager {
public Majordomo(String name) {
super(name);
}
@Override
public void requestApplication(Request request) {
if (request.getRequestType().equals("請假") && request.getNumber() <= 5) {
System.out.println(name + ":" + request.getRequestContent() + "數(shù)量" + request.getNumber() + "被批準");
} else{
if (superior != null) {
superior.requestApplication(request);
}
}
}
}
public class GeneralManager extends Manager {
public GeneralManager(String name) {
super(name);
}
@Override
public void requestApplication(Request request) {
if (request.getRequestType().equals("請假")) {
System.out.println(name + ":" + request.getRequestContent() + "數(shù)量" + request.getNumber() + "被批準");
} else if (request.getRequestType().equals("加薪") && request.getNumber() <= 500) {
System.out.println(name + ":" + request.getRequestContent() + "數(shù)量" + request.getNumber() + "被批準");
} else if (request.getRequestType().equals("加薪") && request.getNumber() > 500) {
System.out.println(name + ":" + request.getRequestContent() + "數(shù)量" + request.getNumber() + "再說吧");
}
}
}
(3)客戶端調(diào)用
public class Client {
public static void main(String[] args) {
CommonManager commonManager = new CommonManager("經(jīng)理");
Majordomo majordomo = new Majordomo("總監(jiān)");
GeneralManager generalManager = new GeneralManager("總經(jīng)理");
commonManager.setSuperior(majordomo);
majordomo.setSuperior(generalManager);
Request request = new Request();
request.setRequestType("請假");
request.setRequestContent("yuzhiyi請假");
request.setNumber(1);
commonManager.requestApplication(request);
Request request1 = new Request();
request1.setRequestType("請假");
request1.setRequestContent("yuzhiyi請假");
request1.setNumber(4);
commonManager.requestApplication(request1);
Request request2 = new Request();
request1.setRequestType("加薪");
request1.setRequestContent("yuzhiyi請求加薪");
request1.setNumber(500);
commonManager.requestApplication(request1);
Request request3 = new Request();
request1.setRequestType("加薪");
request1.setRequestContent("yuzhiyi請求加薪");
request1.setNumber(1000);
commonManager.requestApplication(request1);
}
}
(4)輸出
經(jīng)理:yuzhiyi請假數(shù)量1被批準
總監(jiān):yuzhiyi請假數(shù)量4被批準
總經(jīng)理:yuzhiyi請求加薪數(shù)量500被批準
總經(jīng)理:yuzhiyi請求加薪數(shù)量1000再說吧
責(zé)任鏈模式的使用場景
使用場景:
當(dāng)客戶提交一個請求時,請求時沿鏈傳遞直至有一個 ConcreteHandler 對象負責(zé)處理它。
責(zé)任鏈的優(yōu)缺點
優(yōu)點:
接收者和發(fā)送者都沒有對方的明確信息,且鏈中的對象自己也并不知道鏈的結(jié)構(gòu)。結(jié)果是責(zé)任鏈可簡化對象的相互連接,它們僅需保持一個指向其后繼者的引用,而不需保持它所有的候選者的引用。
隨時地增加或修改一個請求的結(jié)構(gòu)。增強了給對象指派職責(zé)的靈活性。
缺點:
一個請求極有可能到了鏈的末端都得不到處理,或者因為沒有正確配置而得不到處理。