1. 程式人生 > >設計模式11:責任鏈模式

設計模式11:責任鏈模式

責任鏈模式

定義:為了避免請求傳送者與接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連線成一條鏈,並且沿著這條鏈傳遞請求,直到有物件處理它為止,這就是責任鏈模式。

舉個栗子咯,當週杰倫要在你的城市開演唱會時,而你恰好有課,這時候咋辦呢?總不能不去吧,所以只有向老師請假咯。而請假的話,是有個流程滴,當你提交申請表給輔導員時,如果天數在兩天以內的話,輔導員直接給你批准啦,你就可以開溜啦;但是當你請假天數在兩天以上,四天以內的時候,輔導員就沒那個權力批准啦,它就只能把你的申請表交給學院院長,讓院長批准啦;如果天數在四天到七天的話,院長也沒法子處理啦,他只有把你的請假申請表交給校長啦;如果請假天數大於七天...抱歉,請假七天那還讀個毛的書,一律否決,再附送個叫家長來校大禮包....

用程式語言來實現的話,估計很多人第一想到的就是寫一大串if else 語句啦,但在之前討論策略模式的時候,我們就以及說過了這樣的弊端啦,所以我們就要用到我們的責任鏈模式啦

主要角色

Handler: 抽象處理者。定義了一個處理請求的方法。所有的處理者都必須實現該抽象類。 

ConcreteHandler: 具體處理者。處理它所負責的請求,同時也可以訪問它的後繼者。如果它能夠處理該請求則處理,否則將請求傳遞到它的後繼者。 
Client: 事件的發起者 

例項

首先定義一個假條類

public class LeaveRequest {
	private String name;
	private int leaveDays;
	
	public LeaveRequest(String name, int leaveDays) {
		super();
		this.name = name;
		this.leaveDays = leaveDays;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getLeaveDays() {
		return leaveDays;
	}
	public void setLeaveDays(int leaveDays) {
		this.leaveDays = leaveDays;
	}	
}

定義抽象處理者

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

三個具體的處理者

輔導員

public class Instructor extends Leader{

	public Instructor(String name) {
		super(name);
	
	}
	
	public void handleRequest(LeaveRequest LeaveRequest) {
        if(LeaveRequest.getLeaveDays() <= 2){   //小於2天輔導員審批
            System.out.println("輔導員" + name + "審批" +LeaveRequest.getName() + "同學的請假條,請假天數為" + LeaveRequest.getLeaveDays()+ "天。");
        }
        else{     //否則傳遞給院長
            if(this.nextLeader != null){
                this.nextLeader.handleRequest(LeaveRequest);
            }
        }
    }

}

院長

public class Dean extends Leader{
	
	public Dean(String name) {
		super(name);
	
	}
	
	public void handleRequest(LeaveRequest LeaveRequest) {
        if(LeaveRequest.getLeaveDays() <= 4){   //小於4天院長審批
            System.out.println("院長" + name + "審批" +LeaveRequest.getName() + "同學的請假條,請假天數為" + LeaveRequest.getLeaveDays()+ "天。");
        }
        else{     //否則傳遞給校長
            if(this.nextLeader != null){
                this.nextLeader.handleRequest(LeaveRequest);
            }
        }
    }

}

校長

public class President extends Leader{

	public President(String name) {
		super(name);
	
	}
	
	public void handleRequest(LeaveRequest LeaveRequest) {
        if(LeaveRequest.getLeaveDays() <= 7){   //小於7天校長審批
            System.out.println("校長" + name + "審批" +LeaveRequest.getName() + "同學的請假條,請假天數為" + LeaveRequest.getLeaveDays()+ "天。");
        }
        else{
        	System.out.println("叫家長來");
        }
 
    }
}

 客戶端測試

public class Client {
	
	public static void main(String[] args) {
		
		
		 Leader instructor = new Instructor("老王");       //輔導員
	     Leader dean = new Dean("老李");      //院長
	     Leader president = new President("老謝");     //校長
	        
	     instructor.setNextLeader(dean);       //輔導員的後續者是院長
	     dean.setNextLeader(president);         //院長的後繼者是校長
	     
	     LeaveRequest le = new LeaveRequest("我", 1);
	     instructor.handleRequest(le);
	     
	     le = new LeaveRequest("哥", 3);
	     instructor.handleRequest(le);
	     
	     le = new LeaveRequest("qiu", 5);
	     instructor.handleRequest(le);
	     
	     le = new LeaveRequest("ll", 11);
	     instructor.handleRequest(le);
	}

}

 適用場景

  • 有多個物件可以處理同一個請求,具體哪個物件處理該請求由執行時刻自動確定。
  • 在不明確指定接收者的情況下,向多個物件中的一個提交一個請求。
  • 可動態指定一組物件處理請求。

實際開發中的應用

  • Java中,異常機制就是一種責任鏈模式。一個try可以對應多個catch,當第一個catch不匹配型別,則自動跳到第二個catch.
  • Javascript語言中,事件的冒泡和捕獲機制。Java語言中,事件的處理採用觀察者模式。
  • Servlet開發中,過濾器的鏈式處理