简介
责任链模式(Chain of Responsibility Pattern)属于设计模式的行为型模式。责任链模式与多米诺骨牌有点类似,请求在链中从前向后传递,一直到最后一个。当然责任链的处理可以复杂的多。
责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者与请求处理者耦合在一起。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
可以看到在标准的责任链中,请求是只由一个对象来处理的。不过我们不用拘泥于这个定义,责任链的主要目的是将请求处理的各个对象解耦出来,至于在链中传递时有多少个对象处理了请求,其实并不重要。
从定义中可以看出,责任链模式包含的角色有有发送者,请求处理接口,具体请求处理实现及将实现连接起来的链。
发送者:产生请求对象,发起对链的调用 请求处理接口: 定义处理的标准接口,所有的具体请求处理实现都需要实现这个接口,链只需要依赖接口即可 具体请求处理实现:对请求进行处理,并决定是否继续向后传递请求 链:将所有的请求组装到一起,变成一个有序的处理链条
责任链模式可简单可复杂,一般来说接口和实现是必须的,链对象可以简单变为一个 List
,处理顺序也可以简化为 for 循环与发送者耦合到一起。如果处理比较复杂,像 Servlet Filter,网络请求库的Handler等框架则会有一个链对象,而且链中的下一级调用与否是由 handler 来决定的。
在日志打印框架中,我们会定义很多日志级别,不同级别的日志logger我们可以使用责任链模式来串联起来。
//日志级别
public enum LogLevel {
DEBUG, INFO, WARN, ERROR
}
@FunctionalInterface
public interface Logger {
abstract void log(String msg, LogLevel level);
//utitlity methods
default void debug(String msg) {
log(msg, LogLevel.DEBUG);
}
default void info(String msg) {
log(msg, LogLevel.INFO);
}
default void warn(String msg) {
log(msg, LogLevel.WARN);
}
default void error(String msg) {
log(msg, LogLevel.ERROR);
}
default Logger appendNext(Logger logger) {
return (msg, level) -> {
//call self
log(msg, level);
//call next Logger
logger.log(msg, level);
}
}
}
public class LoggerFactory {
public static Logger consoleLogger(LogLevel[] levels) {
EnumSet<LogLevel> set = EnumSet.copyOf(Arrays.asList(levels));
return (msg, level) {
if (set.contains(level)) {
System.out.println("log to console: " + msg);
}
}
}
public static Logger fileLogger(LogLevel[] levels) {
EnumSet<LogLevel> set = EnumSet.copyOf(Arrays.asList(levels));
return (msg, level) {
if (set.contains(level)) {
System.out.println("log to file: " + msg);
}
}
}
public static Logger emailLogger(LogLevel[] levels) {
EnumSet<LogLevel> set = EnumSet.copyOf(Arrays.asList(levels));
return (msg, level) {
if (set.contains(level)) {
System.out.println("log to email: " + msg);
}
}
}
}
/**
* Logger user
*/
public class Application {
public static void main(String[] args) {
Logger logger = LoggerFactory.consoleLogger(LoggerLevel.values()
.appendNext(LoggerFactory.fileLogger(new LogLevel[]{LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR})
.appendNext(LoggerFactory.emailLogger(new LogLevel[]{LogLevel.ERROR});
logger.debug("log will only show in console logger");
logger.info("log will be printed in console and file loggers");
logger.warn("log will show in console and file loggers");
logger.error("log will show in console, file and email loggers");
}
}
if..ele
来判断,而是由各自的类来决定如何处理链的构造要小心,可能造成死循环
纯的责任链一般要求请求只会被一个处理对象处理,也就是说链中的对象要么处理请求,要么调用下一个对象。要求太严格,只起到了解耦逻辑的作用。
日常使用的一般都是不纯的责任链(期待以后这变成责任链的正确定义),每个处理对象处理一部分逻辑,连起来变成整个逻辑。而且每个对象也不一定要传递给下一级,而是终止请求处理(拦截器Filter,Interceptor,Handler都是这种形式)。上面的日志处理例子也是不纯的责任链。
责任链使用中一般都是前后相连的一根链条,这是为了简单。链也可以变成树或有向图,也就是每个处理对象可以由多个后继,增加处理的灵活性(没见过)。