概述
职责链模式使多个对象都有机会处理请求,从而避免请求发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿这条链传递该请求,直到有一个对象处理它为止。
UML
职责链UML
举例
例如员工申请加薪。我们都知道普通员工想要申请加薪,首先需要将加薪的申请书提交给主管,如果主管没有权限处理这个加薪的事情,那么主管就会将申请提交到部门经理那边,由部门经理去处理。如果部门经理也没有权处理的话,就会将申请再提交到总经理或人力资源总监手上,总经理说我可以处理,那么这个加薪申请就可以被处理了。而普通员工并不知道他提交的这个加薪申请被谁处理了,也不知道处理的经过,他只需要知道将申请提交给主管,最后等结果即可。这就是一个典型的职责链机制:客户端发送请求到职责链的链头上,然后这个请求就会在链中的对象之间逐个传递,直到被某个对象处理并返回结果给客户端为止。
例子示意图
加薪流程图
不使用设计模式代码
就拿以上所说到的例子,我们来用代码做一个简单的试验,先不使用职责链模式,就用最简单方式去实现这个场景。
编写一个RaisesRequest类,用来封装请求内容:
package com.dsguo.chain;
public class RaisesRequest {
private String requestName;
private int requestNumber;
public String getRequestName() {
return requestName;
}
public void setRequestName(String requestName) {
this.requestName = requestName;
}
public int getRequestNumber() {
return requestNumber;
}
public void setRequestNumber(int requestNumber) {
this.requestNumber = requestNumber;
}
}
编写管理者类Manager,这个类用于处理用户的请求:
package com.dsguo.chain;
public class Manager {
// 返回处理结果
public void getResult(String position, RaisesRequest raisesRequest) {
if (position.equals("主管")) {
if (raisesRequest.getRequestName().equals("加薪")) {
System.out.println(">>>主管:我无权处理");
} else {
System.out.println(">>>主管:你在说啥");
}
} else if (position.equals("部门经理")) {
if (raisesRequest.getRequestName().equals("加薪")) {
System.out.println(">>>部门经理:我无权处理");
} else {
System.out.println(">>>部门经理:你在说啥");
}
} else if (position.equals("人力资源总监")) {
if (raisesRequest.getRequestName().equals("加薪")) {
System.out.println(">>>人力资源总监:我无权处理");
} else {
System.out.println(">>>人力资源总监:你在说啥");
}
} else if (position.equals("总经理")) {
if (raisesRequest.getRequestName().equals("加薪")
&& raisesRequest.getRequestNumber() <= 1000) {
System.out.println(">>>总经理:ok,批准了");
} else if(raisesRequest.getRequestName().equals("加薪")
&& raisesRequest.getRequestNumber() > 1000){
System.out.println(">>>总经理:emmm我考虑一下");
}else{
System.out.println(">>>总经理:你在说啥");
}
} else {
System.out.println(">>>没有这个职位");
}
}
}
最后编写客户端类Client:
package com.dsguo.chain;
public class Client {
public static void main(String[] args) {
// 封装请求内容
RaisesRequest raisesRequest = new RaisesRequest();
raisesRequest.setRequestName("加薪");
raisesRequest.setRequestNumber(1000);
// 发送给不同的管理者
Manager manager = new Manager();
manager.getResult("主管", raisesRequest);
manager.getResult("部门经理", raisesRequest);
manager.getResult("人力资源总监", raisesRequest);
manager.getResult("总经理", raisesRequest);
}
}
运行结果:
>>>主管:我无权处理
>>>部门经理:我无权处理
>>>人力资源总监:我无权处理
>>>总经理:ok,批准了
ok,从运行结果也可以看到,这样的代码也是勉勉强强实现了我们的需求。但是,很直观的可以看到代码是有多糟糕,Manager类里的if else全都集中在一个方法里,造成一个方法里重复的代码太多。而且不同部门的管理者都在这个方法里,这就违反了单一职责原则,如果我要增加一个部门的管理者或减少一个部门的管理者,都需要去修改这个类里的代码以及客户端的代码,违反了开-闭原则。这样的代码耦合性是相当高的,但是我们要怎么样对这些代码进行解耦呢?那么这时候就需要使用到职责链模式了。
职责链模式改写
抽象一个Manager管理类:
package com.dsguo.chain;
public abstract class Manager {
protected Manager superior;
protected String position;
// 设置管理对象的名称
public Manager(String position) {
this.position = position;
}
// 设置上级对象
public void setSuperior(Manager superior) {
this.superior = superior;
}
// 处理加薪请求的方法
public abstract void raisesRequest(String requestName,int requestNumber);
}
编写主管类,这是具体的处理类,可以处理100元以内的加薪请求:
package com.dsguo.chain;
public class Director extends Manager {
public Director(String position) {
super(position);
}
public void raisesRequest(String requestName, int requestNumber) {
// 有权处理100元以内的加薪
if (requestName.equals("加薪") && requestNumber <= 100) {
System.out.println(position + ":ok,批准了");
} else if (superior != null) {
// 将请求传递给上级
superior.raisesRequest(requestName, requestNumber);
}
}
}
部门经理类,可以处理300元以内的加薪请求:
package com.dsguo.chain;
public class CHO extends Manager {
public CHO(String position) {
super(position);
}
public void raisesRequest(String requestName, int requestNumber) {
// 有权处理600元以内的加薪
if (requestName.equals("加薪") && requestNumber <= 600) {
System.out.println(position + ":ok,批准了");
} else if (superior != null) {
// 将请求传递给上级
superior.raisesRequest(requestName, requestNumber);
}
}
}
总经理类,可以处理1000元以上的加薪请求:
package com.dsguo.chain;
public class GeneralManager extends Manager {
public GeneralManager(String position) {
super(position);
}
public void raisesRequest(String requestName, int requestNumber) {
// 有权处理1000元以上的加薪
if (requestName.equals("加薪") && requestNumber <= 1000) {
System.out.println(position + ":ok,批准了");
}else {
// 1000元以上看心情
System.out.println(position + ":emmm我考虑一下");
}
}
}
员工类,也就是客户端类:
package com.dsguo.chain;
public class Staff {
public static void main(String[] args) {
// 实例化各个管理者对象
Manager director = new Director("主管");
Manager branchManager = new BranchManager("部门经理");
Manager cho = new CHO("人力资源总监");
Manager generalManager = new GeneralManager("总经理");
// 设置上级与下级
director.setSuperior(branchManager);
branchManager.setSuperior(cho);
cho.setSuperior(generalManager);
director.raisesRequest("加薪",100);
director.raisesRequest("加薪",300);
director.raisesRequest("加薪",600);
director.raisesRequest("加薪",1000);
director.raisesRequest("加薪",1500);
}
}
运行结果:
主管:ok,批准了
部门经理:ok,批准了
人力资源总监:ok,批准了
总经理:ok,批准了
总经理:emmm我考虑一下
使用职责链模式来重构之前的代码后,就很好的解决了原来大量的分支判断耦合在一起,造成维护困难、灵活性差且不好扩展的问题。