JAVA设计模式之责任链模式

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】

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值