在实际开发中,对于一个请求我们要经过层层过滤:身份验证 -> 权限验证 -> 实际业务处理。请求沿着一个链在传递,每一层都可以处理该请求。而“职责链模式”就是专门用于处理这种请求链式传递的模式。
1 职责链模式概述
避免将请求发送者与请求接收者耦合在一起,让多个对象都有机会接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
图 职责链结构
- Handler,抽象处理者,定义了一个处理请求的接口及一个抽象处理者类型的下家引用,一般设计为抽象类。处理者可以连城一条链条。
- ConcreteHandler,具体处理者,是抽象处理者的子类,可以处理用户请求。在处理请求之前需要进行判断,看着是否有相应的处理权限,如果可以处理就处理它,否则将请求转发给后继者。在具体处理者中可以访问链中下一对象,以便请求的转发。
public class Request {
private String username;
private String role;
private String info;
public Request(String username, String role, String info) {
this.username = username;
this.role = role;
this.info = info;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
public abstract class Handler {
protected Handler handler;
public void setHandler(Handler handler) {
this.handler = handler;
}
public abstract void handler(Request request);
}
public class UsernameHandler extends Handler{
@Override
public void handler(Request request) {
if ("admin".equals(request.getUsername())) {
System.out.println("用户名错误--终止请求");
} else {
handler.handler(request);
}
}
}
public class RoleHandler extends Handler{
@Override
public void handler(Request request) {
if (!"all".equals(request.getRole())) {
System.out.println("没有相应权限--终止请求");
} else {
handler.handler(request);
}
}
}
public class ServiceHandler extends Handler{
@Override
public void handler(Request request) {
System.out.println("具体业务处理:" + request.getInfo());
System.out.println("请求处理完成");
}
}
public class Client {
private static Handler handler;
static {
Handler handler1 = new UsernameHandler();
Handler handler2 = new RoleHandler();
Handler handler3 = new ServiceHandler();
handler1.setHandler(handler2);
handler2.setHandler(handler3);
handler = handler1;
}
public static void main(String[] args) {
handler.handler(new Request("huang","sell","生成订单"));
System.out.println("---------------");
handler.handler(new Request("admin","all","提现"));
System.out.println("---------------");
handler.handler(new Request("customer","all","查询商品"));
// 运行结果:
// 没有相应权限--终止请求
// ---------------
// 用户名错误--终止请求
// ---------------
// 具体业务处理:查询商品
// 请求处理完成
}
}
职责链模式本身不创建职责链,职责链由客户端创建。
1.1 纯的职责链模式
要求一个具体处理者对象要么承担全部责任,要么将责任推给下家。不允许出现某个具体处理者对象在承担了一部分或者全部责任后又将责任向下传递的情况。
而且,要求一个请求必须被某个处理者所接收,不能出现某个请求未被任何一个处理者对象处理的情况。
1.2 不纯的职责链模式
允许某个请求被一个具体处理者部分处理后再向下传递,或者一个具体处理者处理完某个请求后,后继处理者可以继续处理该请求,而且一个请求可以最终不被任何处理者对象所接收。
2 优缺点
优点:
- 使得一个对象无须知道是其他哪一个对象处理了其请求。对象仅需要知道该请求会被处理即可。接收者和发送者都没有对方明确的信息,且链中对象不需要知道链的结构,由客户端负责链的创建,降低了系统耦合度。
- 请求处理对象仅需维持一个指向后继者的引用,不需要维持它对所有的候选处理者的引用,可简化对象的相互连接。
- 给对象分派职责时,职责链可以提供更多的灵活性,可以通过在运行时对链进行动态的增加或修改来增加或改变处理一个请求的职责。
- 在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需在客户端重新建链即可。符合开闭原则。
缺点:
- 由于一个请求没有明确的接收者,那不能保证它一定会被处理。
- 对于比较长的职责链,请求的处理可能涉及多个处理对象,系统性能受到一定影响,而且在进行代码调试时不太方便。
- 如果建链不当,可能会照成循环调用,将导致系统陷入死循环。
3 适用场景
- 有多个对象处理同一个请求,具体哪个对象处理该请求待运行时刻再确定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交请求。
- 需要动态指定一组对象处理请求。