责任链模式
解决问题
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
方案
职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
结构
抽象处理者(Handler):定义一个请求处理的方法,并维护一个下一个处理节点 Handler 对象的引用;
具体处理者(ConcreteHandler):对请求进行处理,如果不感兴趣,则进行转发.
// 通用代码 class Client { public static void main(String[] args) { Handler handlerA = new ConcreteHandlerA(); Handler handlerB = new ConcreteHandlerB(); handlerA.setnextHanlder(handlerB); handlerA.handleRequest("requestB"); } static abstract class Handler { protected Handler mNextHandler; public void setnextHanlder(Handler successor) { this.mNextHandler = successor; } public abstract void handleRequest(String request); } static class ConcreteHandlerA extends Handler { @Override public void handleRequest(String request) { if ("requestA".equals(request)) { System.out.println(String.format("%s deal with request: %s", this.getClass().getSimpleName(), request)); return; } if (this.mNextHandler != null) { this.mNextHandler.handleRequest(request); } } } static class ConcreteHandlerB extends Handler { @Override public void handleRequest(String request) { if ("requestB".equals(request)) { System.out.println(String.format("%s deal with request: %s", this.getClass().getSimpleName(), request)); return; } if (this.mNextHandler != null) { this.mNextHandler.handleRequest(request); } } } }
适用性
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求
优缺点
优点
- 降低耦合度。它将请求的发送者和接收者解耦。
- 简化了对象。使得对象不需要知道链的结构。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 增加新的请求处理类很方便。
缺点
- 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
- 可能不容易观察运行时的特征,有碍于除错。
经典实现
请假流程
// 请求事件类
public class LeaveRequest {
/**天数*/
private int leaveDays;
/**姓名*/
private String name;
}
// 抽象处理者
public class AbstractLeaveHandler {
/**直接主管审批处理的请假天数*/
protected int MIN = 1;
/**部门经理处理的请假天数*/
protected int MIDDLE = 3;
/**总经理处理的请假天数*/
protected int MAX = 30;
/**领导名称*/
protected String handlerName;
/**下一个处理节点(即更高级别的领导)*/
protected AbstractLeaveHandler nextHandler;
/**设置下一节点*/
protected void setNextHandler(AbstractLeaveHandler handler){
this.nextHandler = handler;
}
/**处理请假的请求,子类实现*/
protected void handlerRequest(LeaveRequest request){
}
}
// 直接上级审批.
public class DirectLeaderLeaveHandler extends AbstractLeaveHandler{
public DirectLeaderLeaveHandler(String name) {
this.handlerName = name;
}
@Override
protected void handlerRequest(LeaveRequest request) {
if(request.getLeaveDays() <= this.MIN){
System.out.println("直接主管:" + handlerName + ",已经处理;流程结束。");
return;
}
if(null != this.nextHandler){
this.nextHandler.handlerRequest(request);
}else{
System.out.println("审批拒绝!");
}
}
}
// 部门经理审批
public class DeptManagerLeaveHandler extends AbstractLeaveHandler {
public DeptManagerLeaveHandler(String name) {
this.handlerName = name;
}
@Override
protected void handlerRequest(LeaveRequest request) {
if(request.getLeaveDays() >this.MIN && request.getLeaveDays() <= this.MIDDLE){
System.out.println("部门经理:" + handlerName + ",已经处理;流程结束。");
return;
}
if(null != this.nextHandler){
this.nextHandler.handlerRequest(request);
}else{
System.out.println("审批拒绝!");
}
}
}
// 总经理审批
public class GManagerLeaveHandler extends AbstractLeaveHandler {
public GManagerLeaveHandler(String name) {
this.handlerName = name;
}
@Override
protected void handlerRequest(LeaveRequest request) {
if(request.getLeaveDays() > this.MIDDLE && request.getLeaveDays() <= this.MAX){
System.out.println("总经理:" + handlerName + ",已经处理;流程结束。");
return;
}
if(null != this.nextHandler){
this.nextHandler.handlerRequest(request);
}else{
System.out.println("审批拒绝!");
}
}
}
public class Demo {
public static void main(String[] args) {
LeaveRequest request = LeaveRequest.builder().leaveDays(20).name("张三").build();
AbstractLeaveHandler directLeaderLeaveHandler = new DirectLeaderLeaveHandler("主管张某");
DeptManagerLeaveHandler deptManagerLeaveHandler = new DeptManagerLeaveHandler("经理李某");
GManagerLeaveHandler gManagerLeaveHandler = new GManagerLeaveHandler("总经理王某");
if(request.leaveDays > 3){
directLeaderLeaveHandler.setNextHandler(deptManagerLeaveHandler);
}
if(request.leaveDays > 5){
deptManagerLeaveHandler.setNextHandler(gManagerLeaveHandler);
}
// 链式处理.
directLeaderLeaveHandler.handlerRequest(request);
}
}
模拟服务器请求的拦截器,包含嵌套责任链.
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) {
Msg msg = new Msg();
msg.setMsg("大家好:),<script>,欢迎访问 本网站. ");
// 创建一条责任链
FilterChain fc = new FilterChain();
// 制定规则
fc.add(new HTMLFilter())
.add(new SensitiveFilter());
// 创建一条责任链
FilterChain fc2 = new FilterChain();
// 制定规则
fc2.add(new FaceFilter()).add(new URLFilter());
// 将第二条责任链接到第一条责任链上.
fc.add(fc2);
// 启动执行责任链
fc.doFilter(msg);
System.out.println(msg);
}
}
class Msg {
String name;
String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "Msg{" +
"msg='" + msg + '\'' +
'}';
}
}
interface Filter {
boolean doFilter(Msg m);
}
class HTMLFilter implements Filter {
@Override
public boolean doFilter(Msg m) {
String r = m.getMsg();
r = r.replace('<', '[');
r = r.replace('>', ']');
m.setMsg(r);
return true;
}
}
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Msg m) {
String r = m.getMsg();
r = r.replaceAll("大家好", "各位老爷好.");
m.setMsg(r);
return false;
}
}
class FaceFilter implements Filter {
@Override
public boolean doFilter(Msg m) {
String r = m.getMsg();
r = r.replace(":)", "^V^");
m.setMsg(r);
return true;
}
}
class URLFilter implements Filter {
@Override
public boolean doFilter(Msg m) {
String r = m.getMsg();
r = r.replace("本网站", "http://konghenying.github.com");
m.setMsg(r);
return true;
}
}
class FilterChain implements Filter {
private List<Filter> filters = new ArrayList<>();
public FilterChain add(Filter f) {
filters.add(f);
return this;
}
// 带参数返回的执行方法.
public boolean doFilter(Msg m) {
for(Filter f : filters) {
// 判断是否还要继续执行,false就退出当前责任链.
if(!f.doFilter(m)) return false;
}
return true;
}
}
框架中实现
servlet 的 Filter,网关的拦截,js的事件冒泡机制.