1. 什么是责任链模式?
创建多个对象,使这些对象行成一条链,并沿着这条链传递请求,直到链上的某个对象决定处理此请求,这就是责任链模式。
接收请求的对象形成一条链,这些对象在链上具有层级关系的。这些对象可以处理请求,也可以传递请求,直到有对象处理此请求为止。
责任链模式归根结底就是多重判断,和if、else if是相同的功能,但是条件比较多的情况下,使用if/else会造成代码臃肿,不易于扩展和维护。责任链模式将判断语句放到处理对象中,这样将请求和处理解耦,便于扩展和维护。
责任链模式是对象的行为模式。
2. 角色
图片源于网络
抽象处理者角色(Handler):此类一般是一个抽象类,其中定义了处理请求的抽象方法(handleMessage,示例中为write方法)和传递请求给下一个处理对象的方法(handleRequest)。其中有一个自身的引用(nextHandler),用于接收下一个请求者对象。
具体处理者角色(ConcreteHandler):具体请求者必须继承完善Handler类,提供自己的处理方法实现。可以有多个具体处理者,一般这些具体处理者之间具有层级关系。
调用者角色(Client):调用者有一个Handler的引用,一般此类是一个工具类,专门用于生成对象链。将请求发送者和请求处理者解耦。
3. 优点
(1)将请求的发送者和接收者解耦,请求发送者不知道请求是怎么传递的,也不知道请求是哪个对象处理的。
(2)良好的扩展性。可以很方便的扩展请求处理对象。
(3)可以解决多层if/else嵌套造成的代码臃肿问题,将判断放到处理类中简洁明了。
4. 缺点
(1)不能保证请求一定被处理,如果没有对象处理请求可能掉落到链的末端。
(2)很可能出现请求处理对象循环调用,出现死循环的情况。
(3)责任链模式会增加系统理解难度,不容易观察运行时的特征,增加调试难度,有碍于排查bug。
5. 使用场景
(1)当有多个对象处理一个请求的情况下可以使用责任链模式。
(2)代码中存在多层if/else嵌套的情况下,可以使用责任链模式将判断放到到处理类中。
6. 示例代码
(1)抽象处理者角色
/**
* 日志抽象处理者
*/
public abstract class AbstractLogHandler {
//当前日志级别
protected int level;
//下一个请求处理者
protected AbstractLogHandler nextHandler;
public void setNextHandler(AbstractLogHandler nextHandler) {
this.nextHandler = nextHandler;
}
public AbstractLogHandler getNextHandler() {
return nextHandler;
}
/**
* 传递请求
*/
public final void handleRequest(int logLevel,String msg){
if(this.level<logLevel){
//当前处理对象没有处理权限
getNextHandler().handleRequest(logLevel, msg);
}else{
write(msg);
}
}
/**
* 处理请求:输出日志记录抽象方法,需子类提供实现
*/
public abstract void write(String msg);
}
(2)具体处理者角色
/**
* 普通日志信息具体处理类
*/
public class InfoLogHandle extends AbstractLogHandler {
public InfoLogHandle(int level) {
this.level=level;
}
@Override
public void write(String msg) {
System.out.println("info:"+msg);
}
}
/**
* 警告日志具体处理类
*/
public class WarnLogHandle extends AbstractLogHandler {
public WarnLogHandle(int level) {
this.level=level;
}
@Override
public void write(String msg) {
System.out.println("warn:"+msg);
}
}
/**
* 错误日志信息具体处理类
*/
public class ErrorLogHandle extends AbstractLogHandler {
public ErrorLogHandle(int level) {
this.level=level;
}
@Override
public void write(String msg) {
System.out.println("error:"+msg);
}
}
(3)调用者角色
/**
* 日志对象生成工具类
*/
public class LoggerManager {
// 普通日志级别
public static int INFO = 1;
// 警告日志级别
public static int WARN = 2;
// 错误日志级别
public static int ERROR = 3;
/**
* 生成处理链
* 一般处理对象之间存在一个层级关系
* 此处,INFO权限最低,ERROR权限最高
*/
public static AbstractLogHandler getLogger() {
AbstractLogHandler info = new InfoLogHandle(INFO);
AbstractLogHandler warn = new WarnLogHandle(WARN);
AbstractLogHandler error = new ErrorLogHandle(ERROR);
// 设置处理链
info.setNextHandler(warn);
warn.setNextHandler(error);
return info;
}
}
(4)测试代码
public class Client {
public static void main(String[] args) {
AbstractLogHandler logger=LoggerManager.getLogger();
logger.handleRequest(LoggerManager.INFO, "用户A登录系统");
//error级别的日志,将跳过info和warn,进入error处理者
logger.handleRequest(LoggerManager.ERROR, "系统错误");
//warn级别将跳过info级别的处理者
logger.handleRequest(LoggerManager.WARN,"系统警告");
}
}
(5)测试结果
info:用户A登录系统
error:系统错误
warn:系统警告
参考文章 http://www.jianshu.com/p/d65eeeed6754
【四川乐山程序员联盟,欢迎大家加群相互交流学习5 7 1 8 1 4 7 4 3】