責任鏈模式
閱讀過handler源碼的同學,可能還有印象,handler的message存在隊列中是以鏈式結構存在的,所以,這裏,我們的責任鏈模式,核心就是一個鏈式的結構。
當一個對象持有對下一個對象的引用,這樣就會形成一條鏈,請求在這條鏈上傳遞,直到某一對象決定處理該請求。但是發出者並不清楚到底最終哪個對象會處理該請求,所以,責任鏈模式可以實現,在隱瞞客戶端的情況下,對系統進行動態的調整。
我們還是舉一個現實的例子:現在孩子上學,要有學籍才行,當我們先去找學校,學校說要教育局辦學籍,去到教育局,說要派出所的戶口本,去到派出所,說要醫院的出生證明,於是去到醫院拿到了出生證明,再回到派出所辦理戶口本,再去教育局辦理學籍。這樣就是一個從上至下再回來的一個完整的處理。
我們來看一下代碼
抽象一個類,所有組織的父類,在父類方法operation中對事件進行處理,子類正常情況下不應複寫此類。
/**
* @author: hx
* @Time: 2019/5/22
* @Description: Org
*/
public abstract class Org {
private String name;
private Org next;
public Org(String name) {
this.name = name;
}
public Org setNext(Org next) {
this.next = next;
return next;
}
/**
* 執行操作
*/
public boolean operation(Parents parents){
if (solve(parents)){
System.out.println("---"+name + "能處理此問題");
return true;
}else if (next != null){
System.out.println("---"+name + "不能處理此問題,下一級處理");
if (next.operation(parents)) {
System.out.println("---"+name + "的下一級處理成功,本級再次處理");
solve(parents);
return true;
}else {
System.out.println("---"+name + "的下一級處理失敗");
failed(parents);
}
return false;
}else {
System.out.println("---"+name+ "已經是最後一級");
failed(parents);
return false;
}
}
/**
* 處理操作
* @param parents
*/
protected abstract boolean solve(Parents parents);
/**
*
* @param parents
* @return
*/
protected abstract void failed(Parents parents);
}
再寫一個有個要上學的孩子的父母類,包含出生日期,出生證明,戶口本,學籍這些關鍵的字段。
/**
* @author: hx
* @Time: 2019/5/22
* @Description: Parents
*/
public class Parents {
private String birthCertificate;
private String householdRegister;
private String studentProof;
private String birthday;
public String getBirthCertificate() {
return birthCertificate;
}
public void setBirthCertificate(String birthCertificate) {
this.birthCertificate = birthCertificate;
}
public String getHouseholdRegister() {
return householdRegister;
}
public void setHouseholdRegister(String householdRegister) {
this.householdRegister = householdRegister;
}
public String getStudentProof() {
return studentProof;
}
public void setStudentProof(String studentProof) {
this.studentProof = studentProof;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
}
下面就是集成org組織的子類實現了,學校,教育局,派出所,醫院。
/**
* @author: hx
* @Time: 2019/5/22
* @Description: School
*/
public class School extends Org {
public School() {
this("學校");
}
public School(String name) {
super(name);
}
@Override
protected boolean solve(Parents parents) {
if (parents.getStudentProof()!= null){
System.out.println("有學籍證明,可以入學");
return true;
}else{
System.out.println("沒有學籍證明,需要去教育局辦理");
return false;
}
}
@Override
protected void failed(Parents parents) {
System.out.println("失敗-沒有學籍證明,教育局不給辦理");
}
}
/**
* @author: hx
* @Time: 2019/5/22
* @Description: EducationBureau
*/
public class EducationBureau extends Org {
public EducationBureau() {
this("教育局");
}
public EducationBureau(String name) {
super(name);
}
@Override
protected boolean solve(Parents parents) {
if (parents.getHouseholdRegister() != null){
parents.setStudentProof("學籍");
System.out.println("有戶口本,可以辦理學籍");
return true;
}else {
System.out.println("沒有戶口本,需派出所辦理");
return false;
}
}
@Override
protected void failed(Parents parents) {
System.out.println("失敗-沒有戶口本,派出所辦不給辦理");
}
}
/**
* @author: hx
* @Time: 2019/5/22
* @Description: PoliceStation
*/
public class PoliceStation extends Org {
public PoliceStation() {
this("派出所");
}
public PoliceStation(String name) {
super(name);
}
@Override
protected boolean solve(Parents parents) {
if (parents.getBirthCertificate() != null){
parents.setHouseholdRegister("戶口本");
System.out.println("有出生證明,辦理戶口本");
return true;
}else {
System.out.println("沒有出生證明,需醫院開證明");
return false;
}
}
@Override
protected void failed(Parents parents) {
System.out.println("失敗-沒有出生證明,醫院不給開證明");
}
}
/**
* @author: hx
* @Time: 2019/5/22
* @Description: Hospital
*/
public class Hospital extends Org {
public Hospital() {
this("醫院");
}
public Hospital(String name) {
super(name);
}
@Override
protected boolean solve(Parents parents) {
if (parents.getBirthday() != null){
parents.setBirthCertificate("出生證明");
System.out.println("沒有出生證明,開一個出生證明");
return true;
}else{
System.out.println("不知道出生日期,不給開出生證明");
return false;
}
}
@Override
protected void failed(Parents parents) {
System.out.println("失敗-醫院不給開出生證明");
}
}
先來一個有出生日期的父母
public static void main(String[] args){
Parents parents = new Parents();
parents.setBirthday("1-1");
School school = new School();
EducationBureau educationBureau = new EducationBureau();
PoliceStation policeStation = new PoliceStation();
Hospital hospital = new Hospital();
school.setNext(educationBureau).setNext(policeStation).setNext(hospital);
school.operation(parents);
}
輸出結果:
沒有學籍證明,需要去教育局辦理
---學校不能處理此問題,下一級處理
沒有戶口本,需派出所辦理
---教育局不能處理此問題,下一級處理
沒有出生證明,需醫院開證明
---派出所不能處理此問題,下一級處理
沒有出生證明,開一個出生證明
---醫院能處理此問題
---派出所的下一級處理成功,本級再次處理
有出生證明,辦理戶口本
---教育局的下一級處理成功,本級再次處理
有戶口本,可以辦理學籍
---學校的下一級處理成功,本級再次處理
有學籍證明,可以入學
再來看一個孩子沒有出生日期的父母
public static void main(String[] args){
Parents parents = new Parents();
School school = new School();
EducationBureau educationBureau = new EducationBureau();
PoliceStation policeStation = new PoliceStation();
Hospital hospital = new Hospital();
school.setNext(educationBureau).setNext(policeStation).setNext(hospital);
school.operation(parents);
}
輸出結果:
沒有學籍證明,需要去教育局辦理
---學校不能處理此問題,下一級處理
沒有戶口本,需派出所辦理
---教育局不能處理此問題,下一級處理
沒有出生證明,需醫院開證明
---派出所不能處理此問題,下一級處理
不知道出生日期,不給開出生證明
---醫院已經是最後一級
失敗-醫院不給開出生證明
---派出所的下一級處理失敗
失敗-沒有出生證明,醫院不給開證明
---教育局的下一級處理失敗
失敗-沒有戶口本,派出所辦不給辦理
---學校的下一級處理失敗
失敗-沒有學籍證明,教育局不給辦理
這樣我們就可以看到,以及以及來處理,每一級的處理都只關聯到下一級,除了知道下一級之外,對其他的對想都毫無所知。
熟悉的同學可能發現,這個非常像android中事件的處理機制。沒錯,android中的事件處理的確也是這樣的,只不過android中的事件處理其阿里,比我們這裏的簡答的demo要複雜一些,處理了很多不同類型的事件,也有攔截的功能,有興趣的同學可以瞭解一下android的事件傳遞機制。
鏈式的結構可以是一條鏈,可以是一個樹,還可以是一個環,模式是不約束這個的,只要自己去實現就行,但是,在一個時刻,只能由一個對象傳給另一個對象處理,不能同時傳給多個對象來處理。
事件的開始,我們只交給第一個對象來處理,至於後面誰來處理的,我們就不關心了,解耦事件最終處理和請求處理的人之間的關係,如果不採用這種方法,那請求處理的人,就必須知道所有的環節的功能,這在現實中其實基本是不可能的。
責任鏈模式,還可以動態的修改事件處理順序,擁有非常良好的擴展性,處理環節之間,也是解耦的,只關心自己的部分。
但是,因爲處理事件在鏈上傳遞,需要一個一個的尋找,需要花費一定的時間。