設計模式:責任鏈模式(ChainOfResponsibility)

什麼是責任鏈模式

責任鏈模式:將能夠處理同一類請求的對象連成一條鏈,所提交的請求沿着鏈傳遞,鏈上的對象逐個判斷是否有能力處理該請求,如果能則處理,如果不能則傳遞給鏈上的下一個對象。

鏈表方式定義責任鏈

如果try,catch一樣,先判斷第一個catch是否符合處理異常,如果不符合則交給下一個catch,依此類推找到可以處理的catch.

非鏈表方式實現責任鏈

通過集合,數組生成責任鏈,更加的實用.實際上,很多項目中,每個具體的Handler並不是由團隊開發定義的,而是項目上線後由外部單位追加的,所以使用鏈表方式定義COR鏈就很困難.

添加新的處理對象

由於責任鏈的創建完全符合在客戶端,因此新增新的具體處理者對原有類庫沒有任何影響.只需添加新的類,然後在客戶端調用時添加即可.

經典案例

案例: 我們可以在請假處理流程中,增加新的“副總經理”角色,審批大於等於 * 10天,小於20天的請假。審批流程變爲: ① 如果請假天數小於3天,主任審批 。② 如果請假天數大於等於3天,小於10天,經理審批 。③ 大於等於10天,小於20天的請假,副總經理審批 。 ④ 如果大於等於20天,小於30天,總經理審批 。⑤ 如果大於等於30天,提示拒絕

請假的基本信息:

/**
 * 
 * @author 233admincol
 *@description 封裝請假的基本信息
 */
public class LeaveRequest {

	private String empName;
    private int leaveDays;
    private String reason;
 
    public LeaveRequest(String empName, int leaveDays, String reason) {
        this.empName = empName;
        this.leaveDays = leaveDays;
        this.reason = reason;
    }
 
    public String getEmpName() {
        return empName;
    }
 
    public void setEmpName(String empName) {
        this.empName = empName;
    }
 
    public int getLeaveDays() {
        return leaveDays;
    }
 
    public void setLeaveDays(int leaveDays) {
        this.leaveDays = leaveDays;
    }
 
    public String getReason() {
        return reason;
    }
 
    public void setReason(String reason) {
        this.reason = reason;
    }
}

領導的抽象類

public abstract class Leader {
protected String name;
protected Leader nextLeader;//責任鏈上的後繼對象
public Leader(String name) {
	this.name=name;
}
//設定責任鏈上的後繼對象
public void setNextLeader(Leader nextLeader) {
	this.nextLeader=nextLeader;
}
//處理請求的核心的業務方法
public abstract void handRequest(LeaveRequest request);
}

經理

public class Manager extends Leader{
	public Manager(String name) {
        super(name);
    }
 
    // 責任鏈操作
    @Override
    public void handRequest(LeaveRequest request) {
        if(request.getLeaveDays() >= 3 && request.getLeaveDays() < 10) {
            System.out.println("員工: " + request.getEmpName() + "請假,天數:" + request.getLeaveDays() + ",理由: " + request.getReason());
            System.out.println("經理: " + this.name + "審批通過...");
        }else {
            // 如果當前責任鏈無法處理會轉向下家責任鏈
            if(this.nextLeader != null) {
                this.nextLeader.handRequest(request);
            }
        }
    }
}

副總經理

public class ViceGeneralManager extends Leader{
	 public ViceGeneralManager(String name) {
	        super(name);
	    }
	 
	    @Override
	    public void handRequest(LeaveRequest request) {
	        if(request.getLeaveDays() < 20) {
	            System.out.println("員工: " + request.getEmpName() + "請假,天數:" + request.getLeaveDays() + ",理由: " + request.getReason());
	            System.out.println("副總經理: " + this.name + "審批通過...");
	        }else {
	            System.out.println(request.getEmpName() + "請假: " + request.getLeaveDays() + "天,審批不通過...");
	        }
	    }

}

總經理

public class GeneralManager extends Leader{
	public GeneralManager(String name) {
        super(name);
    }
 
    @Override
    public void handRequest(LeaveRequest request) {
        if(request.getLeaveDays() < 30) {
            System.out.println("員工: " + request.getEmpName() + "請假,天數:" + request.getLeaveDays() + ",理由: " + request.getReason());
            System.out.println("總經理: " + this.name + "審批通過...");
        }else {
            System.out.println(request.getEmpName() + "請假: " + request.getLeaveDays() + "天,審批不通過...");
        }
    }
}

主任

public class Director extends Leader{
	 public Director(String name) {
	        super(name);
	    }
	 
	    @Override
	    public void handRequest(LeaveRequest request) {
	        if(request.getLeaveDays() < 3) {
	            System.out.println("員工: " + request.getEmpName() + "請假,天數:" + request.getLeaveDays() + ",理由: " + request.getReason());
	            System.out.println("主任: " + this.name + "審批通過...");
	        }else {
	            if(this.nextLeader != null) {
	                this.nextLeader.handRequest(request);
	            }
	        }
	    }
}

測試代碼

public class Test {
	 public static void main(String[] args) {
	        Leader a = new Director("張三");  // 主任
	        Leader b = new Manager("李四");   // 經理
	        Leader c = new ViceGeneralManager("王五");    // 副總經理
	        Leader d = new GeneralManager("馬六");    // 總經理
	 
	        // 組織責任鏈對象的關係
	        a.setNextLeader(b); // 主任的上級領導是經理
	        b.setNextLeader(c); // 經理的上級領導是副總經理
	        c.setNextLeader(d); // 副總經理的上級領導是總經理
	 
	        // 開始請假操作
	        LeaveRequest tom = new LeaveRequest("Tom",19,"回英國探親!");
	        a.handRequest(tom);
	    }

}

在這裏插入圖片描述

開發中的常見場景

  • Java中,異常機制就是一種責任鏈模式。一個try可以對應多個catch,當第一個catch不匹配類型,則自動跳到第二個catch.
  • Javascript語言中,事件的冒泡和捕獲機制。Java語言中,事件的處理採用觀察者模式。
  • Servlet開發中,過濾器的鏈式處理
  • Struts2中,攔截器的調用也是典型的責任鏈模式
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章