1. 程式人生 > >【java設計模式】之 責任鏈(chain of resposibility)模式

【java設計模式】之 責任鏈(chain of resposibility)模式

  責任鏈模式,顧名思義,就是一條鏈。這個鏈到底是怎麼執行的呢?它主要是將能夠處理同一類請求的物件連成一條鏈,所提交的請求沿著鏈傳遞,鏈上的物件逐個判斷是否有能力處理該請求,如果能則處理,如果不能則傳遞給鏈上的下一個物件進行處理,以此類推。
  比如說公司請假需要審批,舉個不恰當的例子,如果請假小於3天,主管審批;3-10天的,經理審批;10-30天的,總經理審批;超過30天的,不批准等等。這就得一步步去判斷,如果撇開設計模式不看的話,那麼我們可以使用if…else…把它解決了,但是問題可想而知,實際中的複雜程度時遠遠超過這個例子的。
  下面使用責任鏈模式來實現一下這個場景,先來看一下它們之間的關係結構:
這裡寫圖片描述


  Leader是個抽象類,裡面有個方法是獲取下一個Leader,Director、Manager和GeneralManager分別繼承這個抽象類。LeaveRequest中封裝了請假的相關資訊。下面來實現一下這個責任鏈模式。
首先是封裝請假資訊的類:

/**
 * @Description 封裝請假的基本資訊
 * @author Ni Shengwu
 *
 */
public class LeaveRequest {

    private String name;
    private int leaveDays;
    private String reason;

    public
LeaveRequest(String name, int leaveDays, String reason) { super(); this.name = name; this.leaveDays = leaveDays; this.reason = reason; } //省略get和set方法 }

然後就是定義Leader這個抽象類了

/**
 * @Description 領導的抽象類
 * @author Ni Shengwu
 *
 */
public abstract class Leader
{
protected String name; protected Leader nextLeader; //責任鏈上的後繼物件,即這個物件無法處理,就轉移給下一個Leader public Leader(String name) { super(); this.name = name; } // 設定責任鏈上的後繼物件 public void setNextLeader(Leader nextLeader) { this.nextLeader = nextLeader; } /** * 處理請求的核心的業務方法 * 需要不同繼承該類的領導自己實現 */ public abstract void handleRequest(LeaveRequest request); }

主管、經理和總經理都需要繼承該類,並實現處理請假的這個方法。

/**
 * @Description 主任
 * @author Ni Shengwu
 *
 */
public class Director extends Leader {

    public Director(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest request) {

        int days = request.getLeaveDays(); //獲取請假天數
        String name = request.getName(); //獲取請假人姓名
        String reason = request.getReason(); // 獲取請假理由

        if(days <= 3) { //如果滿足3天內的要求,主任直接審批
            System.out.println("員工" + name + "請假" + days + "天,理由:" + reason);
            System.out.println("主任" + this.name + "審批通過");
        } else {
            System.out.println("請假天數過多,主任" + this.name + "沒法處理");
            if(this.nextLeader != null) { //否則,如果鏈上存在下一個Leader,就讓他處理
                this.nextLeader.handleRequest(request);
            } 
        }
    }

}
/**
 * @Description 經理
 * @author Ni Shengwu
 *
 */
public class Manager extends Leader {

    public Manager(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest request) {

        int days = request.getLeaveDays(); //獲取請假天數
        String name = request.getName(); //獲取請假人姓名
        String reason = request.getReason(); // 獲取請假理由

        if(days <= 10) { //如果滿足10天內的要求,經理直接審批
            System.out.println("員工" + name + "請假" + days + "天,理由:" + reason);
            System.out.println("經理" + this.name + "審批通過");
        } else {
            System.out.println("請假天數過多,經理" + this.name + "沒法處理");
            if(this.nextLeader != null) { //否則,如果鏈上存在下一個Leader,就讓他處理
                this.nextLeader.handleRequest(request);
            } 
        }
    }

}
/**
 * @Description 總經理
 * @author Ni Shengwu
 *
 */
public class GeneralManager extends Leader {

    public GeneralManager(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest request) {

        int days = request.getLeaveDays(); //獲取請假天數
        String name = request.getName(); //獲取請假人姓名
        String reason = request.getReason(); // 獲取請假理由

        if(days <= 30) { //如果滿足30天內的要求,總經理直接審批
            System.out.println("員工" + name + "請假" + days + "天,理由:" + reason);
            System.out.println("總經理" + this.name + "審批通過");
        } else {
            System.out.println("請假天數過多,總經理" + this.name + "沒法處理");
            if(this.nextLeader != null) { //否則,如果鏈上存在下一個Leader,就讓他處理
                this.nextLeader.handleRequest(request);
            } else {
                System.out.println("請假不成功");
            }
        }
    }

}

  由此可見,他們處理請求的條件是不同的,而且只要不是自己處理範圍之內的,就會將請求傳給鏈上的下一位來處理。接下來寫個客戶端模擬下:

public class Client {

    public static void main(String[] args) {

        Leader director = new Director("張三");
        Leader manager = new Manager("李四");
        Leader gManager = new GeneralManager("王五");

        // 組織好責任鏈物件的關係
        director.setNextLeader(manager);
        manager.setNextLeader(gManager);

        // 開始請假操作
        LeaveRequest request = new LeaveRequest("倪升武", 15, "在家睡覺");
        director.handleRequest(request);
    }

}

執行結果:

請假天數過多,主任張三沒法處理
請假天數過多,經理李四沒法處理
員工倪升武請假15天,理由:在家睡覺
總經理王五審批通過

  在實際中,設定這個鏈可以放到配置檔案中,可以直接修改配置檔案即可,這個責任鏈模式擴充套件性也很好,比如現在有個副經理,專門處理10-20天的請假,那麼我只要新新增一個副經理類即可,然後在責任鏈上配置一下就行了,對其他的類沒有影響。
  責任鏈模式使用的地方很多,比如我們常見的try…catch…就是,可以有多個catch,一個個往下判斷;再比如servlet裡面的過濾器,就是一個責任鏈;再比如struts2中的攔截器,也是使用的責任鏈模式。
  
【友情提示】我的 Spring Boot 達人課上線了,您的支援是我創作的最大動力!

掃碼試讀或點此試讀
這裡寫圖片描述
文末福利:“程式設計師私房菜”,一個有溫度的公眾號~
程式設計師私房菜