職責(zé)鏈模式(Chain of Responsibility):使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系,。將這些對(duì)象連成一條鏈,,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它為止,。
適用場(chǎng)景:
1,、有多個(gè)的對(duì)象可以處理一個(gè)請(qǐng)求,哪個(gè)對(duì)象處理該請(qǐng)求運(yùn)行時(shí)刻自動(dòng)確定,;
2,、在不明確指定接收者的情況下,向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求,;
3,、處理一個(gè)請(qǐng)求的對(duì)象集合應(yīng)被動(dòng)態(tài)指定。
通用類(lèi)圖:
在大學(xué)里面當(dāng)班干部,,時(shí)常要向上級(jí)申請(qǐng)各方面的東西,。譬如申請(qǐng)全班外出秋游,,普通同學(xué)將申請(qǐng)表交給班長(zhǎng),班長(zhǎng)簽字之后交給輔導(dǎo)員,,輔導(dǎo)員批準(zhǔn)之后上交到主任辦公室…就是這樣,,一個(gè)請(qǐng)求(這里是一份申請(qǐng)表)有時(shí)候需要經(jīng)過(guò)好幾個(gè)級(jí)別的處理者(這里是輔導(dǎo)員、主任)的審查才能夠最終被確定可行與否,。
在這里表現(xiàn)出來(lái)的是一個(gè)職責(zé)鏈,,即不同的處理者對(duì)同一個(gè)請(qǐng)求可能擔(dān)負(fù)著不同的處理方式、權(quán)限,,但是我們希望這個(gè)請(qǐng)求必須到達(dá)最終拍板的處理者(否則秋游就沒(méi)戲了),。這種關(guān)系就很適合使用職責(zé)鏈模式了。
類(lèi)圖結(jié)構(gòu)如下:
代碼實(shí)現(xiàn)如下: -
-
-
-
-
-
- interface Levels {
- public static final int LEVEL_01 = 1;
- public static final int LEVEL_02 = 2;
- public static final int LEVEL_03 = 3;
- }
-
- abstract class AbstractRequest {
- private String content = null;
-
- public AbstractRequest(String content) {
- this.content = content;
- }
-
- public String getContent() {
- return this.content;
- }
-
-
- public abstract int getRequestLevel();
- }
-
- class Request01 extends AbstractRequest {
- public Request01(String content) {
- super(content);
- }
-
- @Override
- public int getRequestLevel() {
- return Levels.LEVEL_01;
- }
- }
-
-
- class Request02 extends AbstractRequest {
- public Request02(String content) {
- super(content);
- }
-
- @Override
- public int getRequestLevel() {
- return Levels.LEVEL_02;
- }
- }
-
-
- class Request03 extends AbstractRequest {
- public Request03(String content) {
- super(content);
- }
-
- @Override
- public int getRequestLevel() {
- return Levels.LEVEL_03;
- }
- }
-
- abstract class AbstractHandler {
-
- private AbstractHandler nextHandler = null;
-
-
- public final void handleRequest(AbstractRequest request) {
-
-
- if (this.getHandlerLevel() == request.getRequestLevel()) {
- this.handle(request);
- } else {
-
- if (this.nextHandler != null) {
- System.out.println("當(dāng)前 處理者-0" + this.getHandlerLevel()
- + " 不足以處理 請(qǐng)求-0" + request.getRequestLevel());
-
-
- this.nextHandler.handleRequest(request);
- } else {
- System.out.println("職責(zé)鏈上的所有處理者都不能勝任該請(qǐng)求...");
- }
- }
- }
-
-
- public void setNextHandler(AbstractHandler nextHandler) {
- this.nextHandler = nextHandler;
- }
-
-
- protected abstract int getHandlerLevel();
-
-
- protected abstract void handle(AbstractRequest request);
- }
-
- class Handler01 extends AbstractHandler {
- @Override
- protected int getHandlerLevel() {
- return Levels.LEVEL_01;
- }
-
- @Override
- protected void handle(AbstractRequest request) {
- System.out.println("處理者-01 處理 " + request.getContent() + "\n");
- }
- }
-
-
- class Handler02 extends AbstractHandler {
- @Override
- protected int getHandlerLevel() {
- return Levels.LEVEL_02;
- }
-
- @Override
- protected void handle(AbstractRequest request) {
- System.out.println("處理者-02 處理 " + request.getContent()+ "\n");
- }
- }
-
-
- class Handler03 extends AbstractHandler {
- @Override
- protected int getHandlerLevel() {
- return Levels.LEVEL_03;
- }
-
- @Override
- protected void handle(AbstractRequest request) {
- System.out.println("處理者-03 處理 " + request.getContent()+ "\n");
- }
- }
-
- public class Client {
- public static void main(String[] args) {
-
- AbstractHandler handler01 = new Handler01();
- AbstractHandler handler02 = new Handler02();
- AbstractHandler handler03 = new Handler03();
-
-
- handler01.setNextHandler(handler02);
- handler02.setNextHandler(handler03);
-
-
- AbstractRequest request01 = new Request01("請(qǐng)求-01");
- AbstractRequest request02 = new Request02("請(qǐng)求-02");
- AbstractRequest request03 = new Request03("請(qǐng)求-03");
-
-
- handler01.handleRequest(request01);
- handler01.handleRequest(request02);
- handler01.handleRequest(request03);
- }
- }
測(cè)試結(jié)果: - 處理者-01 處理 請(qǐng)求-01
-
- 當(dāng)前 處理者-01 不足以處理 請(qǐng)求-02
- 處理者-02 處理 請(qǐng)求-02
-
- 當(dāng)前 處理者-01 不足以處理 請(qǐng)求-03
- 當(dāng)前 處理者-02 不足以處理 請(qǐng)求-03
- 處理者-03 處理 請(qǐng)求-03
在上面抽象處理者 AbstractHandler 類(lèi)的 handleRequest() 方法中,,被 protected 修飾,并且該方法中調(diào)用了兩個(gè)必須被子類(lèi)覆蓋實(shí)現(xiàn)的抽象方法,,這里是使用了模板方法模式(Template Mehtod),。其實(shí)在這里,抽象父類(lèi)的 handleRequest() 具備了請(qǐng)求傳遞的功能,,即對(duì)某些請(qǐng)求不能處理時(shí),,馬上提交到下一結(jié)點(diǎn)(處理者)中,而每個(gè)具體的處理者僅僅完成了具體的處理邏輯,,其他的都不用理,。
記得第一次看到職責(zé)鏈模式的時(shí)候,我很驚訝于它能夠把我們平時(shí)在代碼中的 if..else.. 的語(yǔ)句塊變成這樣靈活,、適應(yīng)變化,。例如:如果現(xiàn)在輔導(dǎo)員請(qǐng)長(zhǎng)假了,但我們的秋游還是要爭(zhēng)取申請(qǐng)成功呀,,那么我們?cè)?Client 類(lèi)中可以不要?jiǎng)?chuàng)建 handler02,即不要將該處理者組裝到職責(zé)鏈中,。這樣子處理比 if..else..好多了,。或者說(shuō),突然來(lái)了個(gè)愛(ài)管閑事的領(lǐng)導(dǎo),,那么我照樣可以將其組裝到職責(zé)鏈中,。
關(guān)于上面使用場(chǎng)景中提到的3個(gè)點(diǎn):
1、處理者在運(yùn)行時(shí)動(dòng)態(tài)確定其實(shí)是我們?cè)?Client 中組裝的鏈所引起的,,因?yàn)榫唧w的職責(zé)邏輯就在鏈中一一對(duì)應(yīng)起來(lái),;
2、因?yàn)椴淮_定請(qǐng)求的具體處理者是誰(shuí),,所以我們把所有可能的處理者組裝成一條鏈,,在遍歷的過(guò)程中就相當(dāng)于向每個(gè)處理者都提交了這個(gè)請(qǐng)求,等待其審查,。并且在審查過(guò)程中,,即使不是最終處理者,也可以進(jìn)行一些請(qǐng)求的“包裝”操作(這種功能類(lèi)似于裝飾者模式),,例如上面例子中的簽名批準(zhǔn),;
3、處理者集合的動(dòng)態(tài)指定跟上面的第1,、2點(diǎn)類(lèi)似,,即在 Client 類(lèi)中創(chuàng)建了所有可能的處理者。
不足之處:
1,、對(duì)于每一個(gè)請(qǐng)求都需要遍歷職責(zé)鏈,,性能是個(gè)問(wèn)題;
2,、抽象處理者 AbstractHandler 類(lèi)中的 handleRequest() 方法中使用了遞歸,,棧空間的大小也是個(gè)問(wèn)題,。
個(gè)人看法:
職責(zé)鏈模式對(duì)于請(qǐng)求的處理是不知道最終處理者是誰(shuí),,所以是運(yùn)行動(dòng)態(tài)尋找并指定;而命令模式中對(duì)于命令的處理時(shí)在創(chuàng)建命令是已經(jīng)顯式或隱式綁定了接收者,。
|