在人类社会中,责任是一种强大的精神力量,如果人人都有相同的责任,这种社会责任形成一个链,那没有任何解决不了的问题,也没有战胜不了的困难。一个人的强大取决于其自身的责任感,一个国家的强大取决于全体人民的责任感。
责任链模式的定义
官方定义:使多个对象都有机会请求处理,从而避免了请求发送者与接受者之间的耦合关系。将这些对象连成一条链,并沿着该条链传递请求,直到有对象处理它为止。
通俗释义:简单点说,就是通过一条链来传递请求。当第一个请求发送到链上之后,链上的节点会依次处理。
Handler
(抽象处理者):提供一个抽象处理接口,便于子类进行引用扩展。
ConcreteHandler
(具体处理者):继承或者实现抽象类,用于具体业务逻辑处理,可以转发请求到下一个节点处理。
责任链模式的重点是在“链”上,而这个“链”是由多个处理者ConcreteHandler组成,通过通用类图可知,通过一条链来处理进行处理请求,上一个请求决定下一个请求。
责任链模式的通用代码
public abstract class Handler {
private Handler nextHandler;
public final Response handler(RequstContext context){
Response object = null;
//是否是自己的处理器
if (this.getHandlerLevel().equals(context.getLevel())){
object = this.process(context);
}else{
//是否有下一个处理器
if (this.nextHandler != null){
object = this.nextHandler.handler(context);
}else{
//没有适当的处理者,则其他业务处理
}
}
return object;
}
//设置下一个处理者
public void setNext(Handler handler){
this.nextHandler = handler;
}
//子类实现,并定义自己的处理级别
protected abstract Level getHandlerLevel();
//实现具体处理业务逻辑
protected abstract Response process(RequstContext context);
}
/**
* @Description:具体处理者
*/
public class ConcreteHandler1 extends Handler {
@Override
protected Level getHandlerLevel() {
return null;//设置当前处理级别
}
@Override
protected Response process(RequstContext context) {
return null;//实现业务逻辑处理
}
}
/**
* @Description:场景模拟
*/
public class RespClient {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
//设置处理顺序
handler1.setNext(handler2);
handler2.setNext(handler3);
//提交请求获取处理结果
Response result = handler1.process(new RequstContext());
}
}
责任链模式的应用场景
责任链模式在实际的项目中虽说不是多见,但是应用确实很多。一般以下几种场景可适用。
- 多个对象处理同一个请求,具体的请求对象由运行时决定。
- 当遇见动态处理一组请求的时候,可以参考责任链模式。
- 在不明确具体处理对象的时候,将某个人物交给一个处理对象处理。
责任链模式的优缺点
优点:责任链模式最显著的优点就是将请求和处理分开,请求者可以不用关心谁在处理请求,处理者也不必知道请求的全貌,两者实现解耦,提高系统灵活性。
缺点:有两个比较显著的缺点
- 性能问题。每个请求,都是从链头到链尾,如果链非常的长,可想而知,性能堪忧。
- 调试不便。链条越长越不利于调试。
注意:责任链模式的话,其中“链”的长度需要控制,不能无限长,一般在Handler中设置一个最大节点数量,在setNext方法中判断是否已经超过最大长度,超过则不允许链建立,避免无节制的破坏系统。
责任链模式的经典应用
责任链模式在Java程序中很少见到,不过也有一些经典的例子参考。
javax.servlet.Filter#doFilter()
java.util.logging.Logger#log()
下面通过一个校验器的例子来说明责任链模式的用法。
/**
* @Description:基础校验器
*/
public abstract class BaseValidator {
private BaseValidator validator;
public BaseValidator nextValidator(BaseValidator next){
this.validator = next;
return next;
}
//校验器具体逻辑,由子类实现
public abstract boolean check(Map<String,Object> form);
//执行下一个校验器
protected boolean checkNext(Map<String,Object> form){
if (validator == null){
return true;
}
return validator.check(form);
}
}
/**
* @Description:入参校验器
*/
public class ParamValidator extends BaseValidator {
private String actName;//活动名称
private Date requestTime;//请求时间
public ParamValidator(String actName){
this.actName = actName;
this.requestTime = new Date();
}
@Override
public boolean check(Map<String, Object> form) {
String actName = (String) form.get("actName");
if (StringUtils.isBlank(actName)){
return false;
}
form.put("requestTime",requestTime);
return checkNext(form);
}
}
/**
* @Description:规则校验器
*/
public class RuleValidator extends BaseValidator {
private Object rule;//标准规则
@Override
public boolean check(Map<String, Object> form) {
Object object = form.get("ruleData");//表单规则
//规则校验
return checkNext(form);
}
}
/**
* @Description:数据校验器
*/
public class DataValidator extends BaseValidator {
private Object data;//存在的数据
public DataValidator(Object object){
this.data = object;
}
@Override
public boolean check(Map<String, Object> form) {
Object object = form.get("formData");//提交的数据
//数据校验逻辑
return checkNext(form);
}
}