好用的設(shè)計(jì)模式 -- 責(zé)任鏈

責(zé)任鏈?zhǔn)且环N日常開(kāi)發(fā)常用的設(shè)計(jì)模式,這里之所以說(shuō)它好用,是因?yàn)樨?zé)任鏈的形式很貼合面向過(guò)程的開(kāi)發(fā)思路,易于理解,同時(shí)鏈?zhǔn)揭怖陂_(kāi)發(fā)者歸納功能,管理代碼。

其實(shí)這種設(shè)計(jì)模式很容易理解,我們都知道鏈表(單向)的數(shù)據(jù)結(jié)構(gòu):

class Node {
    
    private Node next;
    private Object value;

    ……(構(gòu)造方法)
}

理解鏈表就很容易理解責(zé)任鏈:責(zé)任鏈?zhǔn)怯啥鄠€(gè)執(zhí)行對(duì)象構(gòu)成的,它們都有兩個(gè)共同的屬性:一是“next”,表示下一個(gè)執(zhí)行對(duì)象;二是執(zhí)行方法,也就是說(shuō)當(dāng)前對(duì)象需要進(jìn)行的操作方法。既然所有執(zhí)行對(duì)象都有這兩個(gè)共同的屬性,我們就可以抽象出一個(gè)抽象類,它有一個(gè)基礎(chǔ)屬性“next”,和抽象方法:“handleWork”:

public abstract class Handler {
    
    protected Handler next;

    abstract protected String handleWork(Object obj);
}

看起來(lái)Node和Handler可以對(duì)應(yīng)上,只是說(shuō)Node沒(méi)有具體的行為方法,而Handler有基礎(chǔ)方法。
有以上的基礎(chǔ)知識(shí),咱們來(lái)實(shí)現(xiàn)這樣一個(gè)場(chǎng)景:
咱們有一個(gè)收入證明需要申請(qǐng)公司蓋章,這個(gè)過(guò)程中需要小組領(lǐng)導(dǎo),部門主管,公司財(cái)務(wù)進(jìn)行審批。只有順次通過(guò)之后,才可以最終獲得公章。這里我們可以按照責(zé)任鏈的思路進(jìn)行實(shí)現(xiàn):

1. 創(chuàng)建證明的抽象類 Certification.java,雖然是個(gè)示例,但是我們還是按照真實(shí)設(shè)計(jì)出發(fā),證明的類型可能有很多,比如收入證明,結(jié)婚證明,核算證明等等,咱們抽象出一個(gè)證明類,然后創(chuàng)建它的子類IncomeCertification.java。

public abstract class Certification {

    protected String name;

    /**
     * 1 - 收入證明
     * 2 - 核算證明
     * 3 - 結(jié)婚證明
     */
    private Integer type;

    private String owner;

    //... get and set methods
}
public class IncomeCertification extends Certification {

    private Integer income;

   //... get and set methods
}

ok!entity定義完成,可以看到,收入證明有4個(gè)屬性,其中名稱、類型、擁有者是繼承自父類,具體收入是個(gè)性化屬性?,F(xiàn)在咱們定義責(zé)任鏈執(zhí)行對(duì)象的基類:

public abstract class Handler {

    protected Handler next;

    abstract protected boolean processCertification(Certification cert);
}

對(duì)于小組領(lǐng)導(dǎo)來(lái)說(shuō),他需要確認(rèn)該申請(qǐng)人屬于自己團(tuán)隊(duì):

public class GroupLeaderHandler extends Handler {

    private static List<String> teamMember = new ArrayList<String>();

    static {
        teamMember.add("ruiruiyuzhi");
        teamMember.add("zhangsan");
    }

    @Override
    protected boolean processCertification(Certification cert) {
        if (teamMember.contains(cert.getOwner())) {
            return this.next.processCertification(cert);
        }
        return false;
    }
}

對(duì)于部門領(lǐng)導(dǎo)來(lái)說(shuō),他需要確認(rèn)收入無(wú)誤:

public class DepartmentLeaderHandler extends Handler {

    private static final Integer INCOME_TYPE = 1;
    private static final Integer INCOME = 1000;

    @Override
    protected boolean processCertification(Certification cert) {
        IncomeCertification incomeCert = (IncomeCertification) cert;
        if (INCOME_TYPE.equals(cert.getType()) && INCOME.equals(incomeCert.getIncome())) {
            return this.next.processCertification(cert);
        }
        return false;
    }
}

財(cái)務(wù)人員判斷申請(qǐng)類型為已有類型,則審批通過(guò):

public class FinancialHandler extends Handler {

    private static List<Integer> certType = new ArrayList<Integer>();

    static {
        certType.add(1);
        certType.add(2);
        certType.add(3);
    }
    
    @Override
    protected boolean processCertification(Certification cert) {
        return certType.contains(cert.getType()); 
    }
}

到目前為止我們準(zhǔn)備好了各個(gè)責(zé)任鏈環(huán)節(jié)的執(zhí)行對(duì)象,進(jìn)而需要將其串成鏈,這個(gè)過(guò)程跟鏈表的初始化相似:

    public static void main(String[] args) {
        //1.初始化責(zé)任鏈
        GroupLeaderHandler groupLeaderHandler = new GroupLeaderHandler();
        DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();
        FinancialHandler financialHandler = new FinancialHandler();
        groupLeaderHandler.setNext(departmentLeaderHandler);
        departmentLeaderHandler.setNext(financialHandler);
                                             ……

其次,構(gòu)建待審批的證明對(duì)象:

    public static void main(String[] args) {
        //1.初始化責(zé)任鏈
        GroupLeaderHandler groupLeaderHandler = new GroupLeaderHandler();
        DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();
        FinancialHandler financialHandler = new FinancialHandler();
        groupLeaderHandler.setNext(departmentLeaderHandler);
        departmentLeaderHandler.setNext(financialHandler);
        //2.構(gòu)建證明對(duì)象
        IncomeCertification myIncomeCert = new IncomeCertification();
        myIncomeCert.setIncome(1000);
        myIncomeCert.setName("income certification");
        myIncomeCert.setOwner("ruiruiyuzhi");
        myIncomeCert.setType(1);

這時(shí)候我們就需要進(jìn)入責(zé)任鏈開(kāi)始審核了,但是入口在哪呢?當(dāng)然,你可以強(qiáng)行把GroupLeaderHandler中加入一個(gè)public方法,作為入口,但是這樣做擴(kuò)展性不好,比方說(shuō)這條審核的鏈條有新環(huán)節(jié)加入,或者有環(huán)節(jié)精簡(jiǎn),改變了入口,豈不是需要重新編寫入口?
其實(shí)我們可以把入口放在Handler中,這個(gè)方法意味著從當(dāng)前環(huán)節(jié)開(kāi)始,往下走,這樣我們只需要根據(jù)業(yè)務(wù)需要改變?nèi)肟趯?duì)象即可:

public abstract class Handler {

    protected Handler next;

    abstract protected boolean processCertification(Certification cert);

    public Handler getNext() {
        return next;
    }

    public void setNext(Handler next) {
        this.next = next;
    }
    //從當(dāng)前結(jié)點(diǎn)開(kāi)始,往下走
    public boolean processFromCurrentHandler(Certification cert) {
        return this.processCertification(cert);
    }
}

這樣,我們?cè)贛ain方法中去測(cè)試整個(gè)流程可以發(fā)現(xiàn),責(zé)任鏈的形式跑通了。

public class MainApplication {

    public static void main(String[] args) {
        GroupLeaderHandler groupLeaderHandler = new GroupLeaderHandler();
        DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();
        FinancialHandler financialHandler = new FinancialHandler();
        groupLeaderHandler.setNext(departmentLeaderHandler);
        departmentLeaderHandler.setNext(financialHandler);

        IncomeCertification myIncomeCert = new IncomeCertification();
        myIncomeCert.setIncome(1000);
        myIncomeCert.setName("income certification");
        myIncomeCert.setOwner("ruiruiyuzhi");
        myIncomeCert.setType(1);
        boolean isPass = groupLeaderHandler.processFromCurrentHandler(myIncomeCert);
        if (isPass) {
            System.out.println("get the certification");
        } else {
            System.out.println("reject");
        }
    }
}
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容