设计模式之责任链模式

如有转载,请申明:

转载至 http://blog.csdn.net/qq_35064774/article/details/52102422


1 什么是责任链

 

责任链模式是一种对象的行为模式。

在责任链模式中,很多对象由每一个对象对其下家的引用而接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。

 

举个简单的例子,很多工厂都是流水线式的生产,一个产品的生产要经过很多道工序,这就形成了一条链式结构。每道工序都是一个单独的处理过程,如果产品出了问题,就挑出来,否则就传到下一个工序。


2 责任链的分类

 

实际上,责任链分为纯责任链和不纯责任链。

纯责任链要求每个处理者要么处理要么直接传给下一个处理者。

而不纯责任链则可以处理一部分之后传给下一个处理者。

 

最常见的当然是不纯责任链,上面举的工厂生产的例子就是这样的。

 

 

 

3 怎么实现责任链

 

为了方便理解,我们通过一个问题来入手。

 

 * 现有一串文本需要发送,然后返回一个结果。

 * 但为了防止文本中含有敏感词汇,我们需要对文本进行过滤。

 * 过滤规则很简单:把<>替换成全角的<>;把“草泥马”、“敏感”替换成相应个数的"*"

 * 要求发送文本和返回结果都需要处理,且形成一条链式的顺序,即 发送文本是先通过 过滤规则1、过滤规则2,而返回结果是通过 过滤规则2、过滤规则1

 

 

拿到这个问题,大致的思路是,先造出一个容器,存储过滤规则,然后通过循环来处理文本。

为了代码有个整体轮廓,这次先写测试代码。

 

package com.ittianyu.chain;

public class Test {
	public static void main(String[] args) {
		// 先造一个责任链容器
		FilterChain chain = new FilterChain();
		// 往责任链容器中添加过滤规则
		chain.addFilter(new HtmlFlagFilter())
			.addFilter(new SensitiveFilter());
		// 先假设我们的请求和结果文本是这样的
		Request request = new Request("啊哈哈哈哈 <html> 草泥马 敏感 sssss </html>");
		Response response = new Response("请求处理成功");
		// 开始过滤
		chain.doFilter(request, response, chain);
		// 输出结果
		System.out.println(request.getString());
		System.out.println(response.getString());
	}
}


大致处理过程就是如上了。然后我们开始制作责任链容器。他应该有addFilterdoFilter方法。

 

package com.ittianyu.chain;

import java.util.ArrayList;
import java.util.List;

public class FilterChain implements Filter {
	private List<Filter> filters = new ArrayList<Filter>();
	private int index = 0;
	
	// 添加一条处理规则
	public FilterChain addFilter(Filter filter) {
		filters.add(filter);
		return this;
	}
	
	/**
	 * 处理下一个过滤规则
	 */
	@Override
	public void doFilter(Request request, Response response, FilterChain chain) {
		if(index >= filters.size())
			return;
		Filter filter = filters.get(index);
		index++;
		filter.doFilter(request, response, chain);
	}
	
}

 

稍微难想到的是doFilter方法,因为是责任链,所以不能一次性循环处理完,这样就没有链的过滤意义了。

 

FilterChain 里面我们实现了Filter接口,还是使用了其中的方法doFilter,所以还需要造一个Filter接口。

 

package com.ittianyu.chain;

public interface Filter {
	void doFilter(Request request, Response response, FilterChain chain);
}


你会发现Request Response,这两个类其实很简单的,让你看一下它的实现。

 

package com.ittianyu.chain;

public class Request {
	public String string;

	public String getString() {
		return string;
	}

	public void setString(String string) {
		this.string = string;
	}
	
	public Request(){}
	
	public Request(String string) {
		super();
		this.string = string;
	}
}


package com.ittianyu.chain;

public class Response {
	public String string;

	public String getString() {
		return string;
	}

	public void setString(String string) {
		this.string = string;
	}
	
	public Response(){}
	
	public Response(String string) {
		super();
		this.string = string;
	}
}


其实里面就只有一个字符串。

 

有了Filter接口,我们还需要实现了接口的过滤类。

首先是对<>的过滤类

 

package com.ittianyu.chain;

public class HtmlFlagFilter implements Filter {

	@Override
	public void doFilter(Request request, Response response, FilterChain chain) {
		// 先处理请求
		request.string = filter(request.string);
		// 交给下一个处理者
		chain.doFilter(request, response, chain);
		// 后处理结果
		response.string = filter(response.string);
	}
	
	/**
	 * 把<>替换成全角的
	 * @param string 需要过滤的文本
	 * @return 返回过滤后的文本
	 */
	private String filter(String string) {
		string = string
				.replaceAll("<", "<")
				.replaceAll(">", ">");
		string += "\n---deal by HtmlFlagFilter---\n";
		return string;
	}
	
}

 

需要注意的是doFilter中,先对request进行过滤,然后马上就调用chain.doFilter进行下一条规则的过滤,这样就可以在其他规则处理完成后,才处理返回结果,这样就满足的问题的要求。

同样的,还有对敏感词的过滤规则。

 

package com.ittianyu.chain;

public class SensitiveFilter implements Filter {

	@Override
	public void doFilter(Request request, Response response, FilterChain chain) {
		// 先处理请求
		request.string = filter(request.string);
		// 交给下一个处理者
		chain.doFilter(request, response, chain);
		// 后处理结果
		response.string = filter(response.string);
	}
	
	private String filter(String string) {
		string = string
				.replaceAll("敏感", "**")
				.replaceAll("草泥马", "***");
		string += "\n---deal by SensitiveFilter---\n";
		return string;
	}
	
}


 

到此这个例子就写完了,不信试一下。

 

当然这个例子并没有很好的体现责任链的使用,比如这个例子我们还可以改成,当发现敏感词时,就停止处理了,也就是不交给下一个过滤规则。

 

 

 

4 在什么情况下使用责任链模式

 

 * 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。

 * 在不明确指定接受者的情况下,向多个对象中的一个提交一个请求。

 * 可动态指定一组对象处理请求。

 

 

5 责任链模式的优点和缺点

 

优点:

 * 降低耦合度。

 * 简化对象的相互连接。

 * 增强给对象指派职责的灵活性。

 * 增加新的请求处理类很方便。

 

 

缺点:

 * 不能保证请求一定被接收。

 * 系统性能将受到一定影响,而且在进行代码调试时不太方便。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值