責任鏈模式,顧名思義,就是一條鏈。這個鏈到底是怎么運行的呢?它主要是將能夠處理同一類請求的對象連成一條鏈,所提交的請求沿著鏈傳遞,鏈上的對象逐個判斷是否有能力處理該請求,如果能則處理,如果不能則傳遞給鏈上的下一個對象進行處理,以此類推。
比如說公司請假需要審批,舉個不恰當的例子,如果請假小于3天,主管審批;3-10天的,經理審批;10-30天的,總經理審批;超過30天的,不批準等等。這就得一步步去判斷,如果撇開設計模式不看的話,那么我們可以使用if…else…把它解決了,但是問題可想而知,實際中的復雜程度時遠遠超過這個例子的。
下面使用責任鏈模式來實現一下這個場景,先來看一下它們之間的關系結構:
Leader是個抽象類,里面有個方法是獲取下一個Leader,Director、Manager和GeneralManager分別繼承這個抽象類。LeaveRequest中封裝了請假的相關信息。下面來實現一下這個責任鏈模式。
首先是封裝請假信息的類:
/** * @Description 封裝請假的基本信息 * @author shanheyongmu * */ 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 shanheyongmu * */ 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 shanheyongmu * */ 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 shanheyongmu * */ 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 shanheyongmu * */ 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中的攔截器,也是使用的責任鏈模式。
文章列表