1.java web filter拦截器的实现,客户端发送的请求会沿着filter拦截器的链式结构传递,进行相应的处理。
2.Java 异常处理机制,可以观察java异常抛出的日志,可以看到异常的抛出是以链式结构层层抛出。
某场景下,员工向公司请假或者请求涨薪,如果员工先向经理申请,主管表示没有权限,需要总监批准。而员工再向总监请示,总监表示也没有权限,需要总经理授权。模拟这种情景的代码,如果写在一个类中会发现会出现很多的分支结构。而职责链的出现,能够改善这种情况下的代码,而且员工不需要一个一个向上级请示(员工只是提交申请,并不知道是谁处理他的申请),而是系统根据链式结构进行处理,如果当级管理者没有权限处理该事务,则会传递给其上级进行处理,从而实现了代码之间的低耦合。
职责链模式(Chain of Responsibility):使多个对象都有机会处理该请求,从而避免请求发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有个对象处理它为止。
1. 抽象处理者类
package com.cn.itcast.ChainofResponsibility;
/**
* Created by LJP on 2019/4/21.
*/
public abstract class Handler {
/**
* 具体执行者
*/
protected Handler successor;
/**
* 设置继承者
* @param successor
*/
public void setSuccessor (Handler successor) {
this.successor = successor;
}
/**
* 抽象处理方法
* @param request
*/
public abstract void HandleRequest(int request);
}
2.实际处理者
实际处理者有三个。
package com.cn.itcast.ChainofResponsibility;
/**
* Created by LJP on 2019/4/21.
*/
public class ConcreteHandler1 extends Handler {
/**
*
* @param request
*/
@Override
public void HandleRequest(int request) {
if (request >= 0 && request < 10) {
System.out.println(this.getClass().getSimpleName() + "---" + request);
} else if (successor != null){
successor.HandleRequest(request);
}
}
}
package com.cn.itcast.ChainofResponsibility;
/**
* Created by LJP on 2019/4/21.
*/
public class ConcreteHandler2 extends Handler {
@Override
public void HandleRequest(int request) {
if (request >= 10 && request < 20) {
System.out.println(this.getClass().getSimpleName() + "---" + request);
} else if (successor != null){
successor.HandleRequest(request);
}
}
}
package com.cn.itcast.ChainofResponsibility;
/**
* Created by LJP on 2019/4/21.
*/
public class ConcreteHandler3 extends Handler{
@Override
public void HandleRequest(int request) {
if (request >= 20 && request < 30) {
System.out.println(this.getClass().getSimpleName() + "---" + request);
} else {
System.out.println("该数字无法处理" + "---" + request);
}
}
}
3.测试代码
package com.cn.itcast.ChainofResponsibility;
/**
* Created by LJP on 2019/4/21.
*/
public class test {
public static void main(String[] args) {
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.setSuccessor(h2);
h2.setSuccessor(h3);
int[] requests = {2,3,5,11,20,1,35,28};
for (int i = 0; i < requests.length; i++) {
h1.HandleRequest(requests[i]);
}
System.out.println("执行结束");
}
}
4.输出结果
ConcreteHandler1---2
ConcreteHandler1---3
ConcreteHandler1---5
ConcreteHandler2---11
ConcreteHandler3---20
ConcreteHandler1---1
该数字无法处理---35
ConcreteHandler3---28
执行结束
Process finished with exit code 0
根据程序输出可知,请求会随着链的传递而进行处理。注意:在实际处理类中要判断sucessor是否为空,否则如果没有进行h2.setSuccessor(h3)的情况下会出现空指针异常。异常如下:
ConcreteHandler1---3
ConcreteHandler1---5
ConcreteHandler2---11
Exception in thread "main" java.lang.NullPointerException
at com.cn.itcast.ChainofResponsibility.ConcreteHandler2.HandleRequest(ConcreteHandler2.java:13)
at com.cn.itcast.ChainofResponsibility.ConcreteHandler1.HandleRequest(ConcreteHandler1.java:17)
at com.cn.itcast.ChainofResponsibility.test.main(test.java:15)
Process finished with exit code 1
通过异常信息也可以看出异常的抛出也是链式的结构。可以看到主程序中,客户端只要向h1提出申请,不需要关心是谁帮它处理了请求,这样降低了客户端与服务器之间的耦合度。
1.请求类
package com.cn.itcast.ChainofResponsibility1;
/**
* 请求实体类,用于存储请求类型,请求内容,请求数量
* Created by LJP on 2019/4/21.
*/
public class Request {
private String requestType;
private String requestContent;
private Integer number;
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public void setRequestContent(String requestContent) {
this.requestContent = requestContent;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getRequestType() {
return requestType;
}
public String getRequestContent() {
return requestContent;
}
public Integer getNumber() {
return number;
}
}
2.管理者抽象类
package com.cn.itcast.ChainofResponsibility1;
/**
* Created by LJP on 2019/4/21.
*/
public abstract class Manager {
protected String name;
protected Manager superior;
public Manager(String name) {
this.name = name;
}
public void setSuperior(Manager superior) {
this.superior = superior;
}
public abstract void requestApplications(Request request);
}
3.管理者具体类
package com.cn.itcast.ChainofResponsibility1;
/**
* 经理
* Created by LJP on 2019/4/21.
*/
public class CommonManager extends Manager {
public CommonManager(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
if (request.getRequestType().equals("请假") && request.getNumber() <= 2){
System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",被批准");
} else if (superior != null) {
superior.requestApplications(request);
}
}
}
package com.cn.itcast.ChainofResponsibility1;
/**
* 总监类
* Created by LJP on 2019/4/21.
*/
public class Majordomo extends Manager {
public Majordomo (String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
if (request.getRequestType().equals("请假") && request.getNumber() <= 5){
System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",被批准");
} else if (superior != null) {
superior.requestApplications(request);
}
}
}
package com.cn.itcast.ChainofResponsibility1;
/**
* 总经理类
* Created by LJP on 2019/4/21.
*/
public class GeneralManager extends Manager{
public GeneralManager (String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
if (request.getRequestType().equals("请假")){
System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",被批准");
} else if (request.getRequestType().equals("加薪") && request.getNumber() <= 500) {
System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",被批准");
} else if (request.getRequestType().equals("加薪") && request.getNumber() > 500) {
System.out.println(name + "---" + request.getRequestContent() + "---" + request.getNumber() + ",再说吧");
}
}
}
4.测试类
package com.cn.itcast.ChainofResponsibility1;
/**
* 测试类
* Created by LJP on 2019/4/21.
*/
public class test {
public static void main(String[] args) {
//创建管理者类
Manager commonManager = new CommonManager("张经理");
Manager majordomo = new Majordomo("王总监");
Manager generalManager = new GeneralManager("马总经理");
commonManager.setSuperior(majordomo);
majordomo.setSuperior(generalManager);
//创建请求
Request request = new Request();
request.setRequestType("请假");
request.setRequestContent("小李请假");
request.setNumber(1);
commonManager.requestApplications(request);
Request request1 = new Request();
request1.setRequestType("请假");
request1.setRequestContent("小李请假");
request1.setNumber(4);
commonManager.requestApplications(request1);
Request request2 = new Request();
request2.setRequestType("加薪");
request2.setRequestContent("小李请求加薪");
request2.setNumber(500);
commonManager.requestApplications(request2);
Request request3 = new Request();
request3.setRequestType("加薪");
request3.setRequestContent("小李请求加薪");
request3.setNumber(1000);
commonManager.requestApplications(request3);
System.out.println("执行结束");
}
}
5.测试结果
张经理---小李请假---1,被批准
王总监---小李请假---4,被批准
马总经理---小李请求加薪---500,被批准
马总经理---小李请求加薪---1000,再说吧
执行结束
Process finished with exit code 0
客户端的申请都是通过经理进行发起,但具体的操作者对于客户端来说并不知道。注意在编写具体实现类一定要重写构造方法,这是因为管理者抽象类中有有参构造方法。
优点:1.降低应用程序之间耦合。2.将多种判定分散到各个处理类中,程序更加清晰,各类职责更加明确
缺点:1.在找到正确的处理对象之前,所有条件判定都要执行一遍,当责任链过长,可能会影响性能问题。2.可能会造成某个请求不被处理,所以在程序设计时需要考虑全面。
除了上述关于一个请求可能需要多级审批的情况下,另外,if-else判断较多的情况下也可考虑责任链模式。这里奉上github项目地址,仅供参考。