1. 程式人生 > >設計模式之——責任鏈設計模式

設計模式之——責任鏈設計模式

通常每個接收者都包含對另一個接收者的引用。如果一個物件不能處理該請求,那麼它會把相同的請求傳給下一個接收者,依此類推。

該模式在生活中很常見,比如:汽車製造、物流分揀、食品加工、質量檢測等等,生活中更多的是這樣的非純責任模式,也就是說,每個節點都會根據自己的職責操作自己對應的部分,然後轉交下一節點處理;也有純責任模式,比如質檢,一旦某個節點出問題直接不合格並打回。這種模式一般是從低等級往高等級層層請求。

我們來舉個團建經費申請的例子:

場景設定:

專案經理(500) - 部門主管(1000) - 總經理(2000) - 老闆(2000~5000)

首先抽象出經理,並建立鏈的連線關係

package com.zndroid.dm.ChainOfResponseModel;

/**
 * Created by luzhenyu on 2017/9/18.
 */

/**抽象出可處理的物件,並提供‘鏈’的關聯和具體類的處理請求*/
public abstract class Manager {
    public abstract void request(int mount);//請求入口

    public void setNextManager(Manager nextManager) {
        this.nextManager = nextManager;
    }

    protected Manager nextManager;//提供鏈關聯

    public void done() {
        System.out.println("[OK...]");
    }
}

具體節點

package com.zndroid.dm.ChainOfResponseModel.impl;

import com.zndroid.dm.ChainOfResponseModel.Manager;

/**
 * Created by luzhenyu on 2017/9/18.
 */

public class ProjectManager extends Manager {
    @Override
    public void request(int mount) {
        if (mount <= 500) {
            System.out.println("專案經理審批通過,申請金額:" + mount);
            done();
            return;
        }
        else {
            System.out.println("金額超出專案經理的範圍,開始轉交上級處理...");
            nextManager.request(mount);
        }
    }
}
package com.zndroid.dm.ChainOfResponseModel.impl;

import com.zndroid.dm.ChainOfResponseModel.Manager;

/**
 * Created by luzhenyu on 2017/9/18.
 */

public class DepartmentManager extends Manager {
    @Override
    public void request(int mount) {
        if (mount > 500 && mount <= 1000) {
            System.out.println("部門主管審批通過,申請金額:" + mount);
            done();
            return;
        }
        else {
            System.out.println("金額超出部門主管的範圍,開始轉交上級處理...");
            nextManager.request(mount);
        }
    }
}
package com.zndroid.dm.ChainOfResponseModel.impl;

import com.zndroid.dm.ChainOfResponseModel.Manager;

/**
 * Created by luzhenyu on 2017/9/18.
 */

public class GeneralManager extends Manager {
    @Override
    public void request(int mount) {
        if (mount > 1000 && mount <= 2000) {
            System.out.println("總經理審批通過,申請金額:" + mount);
            done();
            return;
        }
        else {
            System.out.println("金額超出總經理的範圍,開始轉交上級處理...");
            nextManager.request(mount);
        }
    }
}
package com.zndroid.dm.ChainOfResponseModel.impl;

import com.zndroid.dm.ChainOfResponseModel.Manager;

/**
 * Created by luzhenyu on 2017/9/18.
 */

public class BossManager extends Manager {
    @Override
    public void request(int mount) {
        if (mount > 2000 && mount <= 5000) {
            System.out.println("老闆審批通過,申請金額:" + mount);
            done();
            return;
        }
        else {
            System.out.println("老闆哭窮中...");
        }
    }
}
使用如下
/**
         * 職責鏈模式
         * 使多個物件都有可能處理請求,從而避免請求的傳送者和接收者之間的耦合關係。將這個物件連成一條鏈,並沿著這條鏈傳遞請求,直到有一個物件處理它為止。
         *
         * 往往它是一個從最低階到上層的請求方式,職責鏈模式可以靈活的改變內部的傳遞規則,每個人可以動態的制定自己的繼承者。
         * 如果初始層級暫時不在或消失,請求也可以直接傳送給其他層級,後續職責鏈還會繼續進行。而且可以隨時增加和修改處理一個請求的結構,增加了給物件指派的職責的靈活性。
         *
         * 優點:
         * 呼叫者不需知道具體誰來處理請求,也不知道鏈的具體結構,降低了節點域節點的耦合度;可在執行時動態修改鏈中的物件職責,增強了給物件指派職責的靈活性;
         * 缺點:
         * 沒有明確的接收者,可能傳到鏈的最後,也沒得到正確的處理;系統性能會受到影響;程式碼除錯比較繁瑣。
         *
         * 具體應用:
         * OA系統;在java中的實際應用有Servlet中的過濾器(Filter);Struts2的攔截器(Interceptor),生活中大部分流程還是不純的責任鏈,也就是每個節點的物件都有可能
         * 做了對應的操作,高層次的操作要以低層次的為依據,比如:公司請假肯定要部門經理先同意才能走到下一級,而不是說,部門經理不同意就會走到老闆那。
         * */
        //下面來模擬一下公司的團建申請
        //比方說現在有三個老總可以處理團建申請,他們的可以批示的金額分變為:
        //專案經理(500) - 部門主管(1000) - 總經理(2000) - 老闆(2000~5000)

        //建立節點:
        ProjectManager projectManager = new ProjectManager();
        DepartmentManager departmentManager = new DepartmentManager();
        com.zndroid.dm.ChainOfResponseModel.impl.GeneralManager  generalManager= new com.zndroid.dm.ChainOfResponseModel.impl.GeneralManager();
        BossManager bossManager = new BossManager();

        //建立連結:
        projectManager.setNextManager(departmentManager);
        departmentManager.setNextManager(generalManager);
        generalManager.setNextManager(bossManager);

        projectManager.request(3000);
        log("----------------我是分割線-----------------");
執行結果:

[ ======================================== ]
金額超出專案經理的範圍,開始轉交上級處理...
金額超出部門主管的範圍,開始轉交上級處理...
金額超出總經理的範圍,開始轉交上級處理...
老闆審批通過,申請金額:3000
[OK...]
[ ----------------我是分割線----------------- ]
[ ======================================== ]



【歡迎上碼】

【微信公眾號搜尋 h2o2s2】