設計模式——職責鏈模式

chain
閱讀原文請訪問個人博客 BrightLoong's Blog

一. 概述

一. 概述

職責鏈模式(Chain of Responsibility):使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關係。將這個對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止(我的認爲並不必定非要知足這種狀況,也能夠是每一個對象能夠處理請求的一部分,或者是下一個處理對象須要上一個處理對象首先完成一些工做,將請求沿鏈一步一步傳遞,知道請求最終處理完成,既同時兼顧請求處理和請求轉發,固然這個僅僅是我的理解,可能不正確,還請諒解)。html

使用職責鏈模式,發起請求的客戶端並不用知道是鏈中的哪個對象最終處理了這個請求,因此這樣系統的更改能夠在不影響客戶端的狀況下動態地從新組織和分配責任。java

職責鏈模式屬於行爲型模式。git

二. UML類圖解析

職責鏈模式的UML類圖以下:github

chain

  • Handler:處理請求的抽象類,持有一個Handler引用做爲後繼者,setSuccessor(Handler handler)用於設置後繼者;handleRequest(Request request)是處理請求的抽象方法,Request是具體的請求,按照本身的需求定義,能夠簡單的基本類型,集合類,也能夠是自定義的類,等待子類具體實現。
  • ConcreteHandler一、ConcreteHandler2:具體處理者類,處理客戶端請求,也能夠訪問後繼者,按照職責鏈模式的定義,要麼處理請求,要麼轉發請求,不存在二者同時兼顧的行爲。

三. 代碼實現

用向銀行貸款做爲例子,申請的貸款金額不一樣須要不一樣等級的銀行人員進行受權。bash

貸款請求類——LoanRequest

首先建立一個貸款請求,具備基本的貸款金額和貸款人信息。ide

package io.github.brightloong.design.chain;

/** * 貸款請求類 * Created by BrightLoong on 2018/5/17. */
public class LoanRequest {
    /**貸款金額*/
    private Long loanAmount;

    /**貸款人姓名*/
    private String name;

    /** * 構造函數. * @param loanAmount * @param name */
    public LoanRequest(Long loanAmount, String name) {
        this.loanAmount = loanAmount;
        this.name = name;
    }

    public Long getLoanAmount() {
        return loanAmount;
    }

    public void setLoanAmount(Long loanAmount) {
        this.loanAmount = loanAmount;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

複製代碼

抽象處理接口——BankStaff

package io.github.brightloong.design.chain;

/** * 請求處理抽象類. * Created by BrightLoong on 2018/5/17. */
public abstract class BankStaff {

    /**持有的後繼者的引用*/
    private BankStaff nextBankStaff;

    /**設置後繼者*/
    public void setNextBankStaff(BankStaff bankStaff) {
        this.nextBankStaff = bankStaff;
    }

    /**獲取後繼者*/
    public BankStaff getNextBankStaff() {
        return this.nextBankStaff;
    }

    /**抽象處理方法,等待子類實現*/
    public abstract void handleLoan(LoanRequest request);
}

複製代碼

銀行櫃員實現——BankTeller

package io.github.brightloong.design.chain;

/** * Created by BrightLoong on 2018/5/17. */
public class BankTeller extends BankStaff {
    public void handleLoan(LoanRequest request) {
        if (request.getLoanAmount() <= 20000) {
            System.out.println(request.getName() + "申請貸款:" + request.getLoanAmount() + "元," + "由銀行櫃員處理。" );
        } else if (getNextBankStaff() != null) {
            getNextBankStaff().handleLoan(request);
        } else {
            System.out.println("沒法處理的貸款請求。");
        }
    }
}

複製代碼

銀行經理實現——BankManager

package io.github.brightloong.design.chain;

/** * Created by BrightLoong on 2018/5/17. */
public class BankManager extends BankStaff{
    public void handleLoan(LoanRequest request) {
        if (request.getLoanAmount() <= 100000) {
            System.out.println(request.getName() + "申請貸款:" + request.getLoanAmount() + "元," + "由銀行經理處理。" );
        } else if (getNextBankStaff() != null) {
            getNextBankStaff().handleLoan(request);
        } else {
            System.out.println("沒法處理的貸款請求。");
        }
    }
}

複製代碼

銀行行長實現——BankPresident

package io.github.brightloong.design.chain;

/** * Created by BrightLoong on 2018/5/17. */
public class BankPresident extends BankStaff {
    public void handleLoan(LoanRequest request) {
        System.out.println(request.getName() + "申請貸款:" + request.getLoanAmount() + "元," + "由銀行行長處理。" );
    }
}

複製代碼

客戶端調用和輸出

package io.github.brightloong.design.chain;

/** * Created by BrightLoong on 2018/5/17. */
public class Client {
    public static void main(String[] args) {
        //構造職責鏈
        BankStaff bankTeller = new BankTeller();
        BankStaff bankManager = new BankManager();
        BankStaff bankPresident = new BankPresident();
        bankTeller.setNextBankStaff(bankManager);
        bankManager.setNextBankStaff(bankPresident);

        //構造請求
        LoanRequest request = new LoanRequest(10000L, "小明");
        bankTeller.handleLoan(request);

        LoanRequest request2 = new LoanRequest(200000L, "老王");
        bankTeller.handleLoan(request2);
    }
}

複製代碼

輸出結果:函數

小明申請貸款:10000元,由銀行櫃員處理。
老王申請貸款:200000元,由銀行行長處理。
複製代碼

四. 總結

使用場景

  • 有多個對象能夠處理同一個請求,具體哪一個對象處理該請求由運行時刻自動肯定。
  • 在不明確接收者的狀況下,向多個對象中的一個處理提交一個請求。
  • 可動態指定一組對象處理請求。

優勢

  • 實現了請求發送者和接收者的解耦,下降了耦合度。
  • 方便擴展,能夠方便的增長請求處理類。
  • 能夠動態的設置請求處理類的順序,比較靈活。
  • 接收者和發送者都沒有對方的明確信息,且鏈中的對象本身也並不知道鏈的結構。結果是職責鏈可簡化對象的相互鏈接,它們僅須要保持一個指向後繼者的引用。

缺點

  • 請求有可能到了鏈的末端都得不處處理,或者由於沒有正確配置而得不處處理。
  • 若是要配置比較複雜的鏈會致使性能受到影響,而且難於調試,易於出錯

參考:http://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html性能

相關文章
相關標籤/搜索