责任链模式
阅读过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的事件传递机制。
链式的结构可以是一条链,可以是一个树,还可以是一个环,模式是不约束这个的,只要自己去实现就行,但是,在一个时刻,只能由一个对象传给另一个对象处理,不能同时传给多个对象来处理。
事件的开始,我们只交给第一个对象来处理,至于后面谁来处理的,我们就不关心了,解耦事件最终处理和请求处理的人之间的关系,如果不采用这种方法,那请求处理的人,就必须知道所有的环节的功能,这在现实中其实基本是不可能的。
责任链模式,还可以动态的修改事件处理顺序,拥有非常良好的扩展性,处理环节之间,也是解耦的,只关心自己的部分。
但是,因为处理事件在链上传递,需要一个一个的寻找,需要花费一定的时间。