前言:
责任链这种模式老早就看过,主要是听马士兵讲的,可是自己在工作中用的很少,渐渐的就忘了,最近工作中又要用到,就复习了一下,同时看了下大话设计模式和百科里面讲的是一样的,总的来说还是马士兵设计的较为巧妙。
下面正式开始。
1、概述:责任链就是一个个的过滤器组成的, 请求要经过每一个过滤器的处理,最终才能到达终点。这个在生活中有很多例子。比如报销金额审批,可能是先要经理审,经理无权审的要升级到总监审,总监无权审的要升级到CTO审。再比如网站敏感关键字过滤,先要将带有js脚本的过滤掉,再将falun功相关的过滤掉,再将笑脸过滤掉(将笑脸表情变成^_^),经过所有这些过滤,才能将发表的内容存盘。
1.1、上面的例子中分为2种情况:一种是经过第一个过滤器就被拦截掉,就不要走后面的过滤器了;另一种是不存在第一个过滤器拦截的情况,可以一直跑到最后。
2、先实现【经过第一个过滤器就被拦截掉】
2.1、这里举例说明,假设有一个抽象类叫Manager(管理者),它有一个抽象方法叫审批,它还有一个成员变量叫上级。它有3个实现类,分别是DevelopmentManager(开发经理),DevelopDirector(开发总监),CTO。类图如下:
2.2、时序图如下:
2.3、大概核心代码如下:
2.3.1、抽象Manager类
package com.maizijf.test.zerenlian;
/**
* Created by germmy on 17/3/3.
*/
public abstract class Manager {
protected Manager supervior;
public void apply(int req){};
public void setSupervior(Manager supervior) {
this.supervior = supervior;
}
public Manager getSupervior() {
return supervior;
}
}
2.3.2、DevelopmentManager类
package com.maizijf.test.zerenlian;
/**
* Created by germmy on 17/3/3.
*/
public class DeveloperManager extends Manager {
@Override
public void apply(int req) {
super.apply(req);
if(req>=1 && req<20){
System.out.println("开发经理审批了:"+req);
}else{
this.getSupervior().apply(req);
}
}
}
2.3.3、DevelopDirector类
package com.maizijf.test.zerenlian;
/**
* Created by germmy on 17/3/3.
*/
public class DevelopmentDirector extends Manager {
@Override
public void apply(int req) {
super.apply(req);
if(req>=20 && req<30){
System.out.println("开发总监审批了:"+req);
}else{
this.getSupervior().apply(req);
}
}
}
2.3.4、CTO类
package com.maizijf.test.zerenlian;
/**
* Created by germmy on 17/3/3.
*/
public class Cto extends Manager {
@Override
public void apply(int req) {
super.apply(req);
if(req>=30 && req<50){
System.out.println("CTO审批了:"+req);
}else{
System.out.println("CTO审批不了:"+req);
}
}
}
2.3.5、Junit Test类
package com.maizijf.test.zerenlian;
import org.junit.Test;
/**
* Created by germmy on 17/3/3.
*/
public class ManagerTest {
@Test
public void testManager(){
//1.先创建几个管理者
Manager dm=new DeveloperManager();
Manager dd=new DevelopmentDirector();
Manager cto=new Cto();
//2.设置他们的上级
dm.setSupervior(dd);
dd.setSupervior(cto);
//3.开始让他们审批
dm.apply(1);
dm.apply(20);
dm.apply(35);
dm.apply(50);
}
}
3、再实现【不存在第一个过滤器拦截】的情况
3.1、同样举例说明,论坛里用户会发帖,后台要根据发帖的内容进行一系列的过滤。假设有一个接口叫做Filter,它只有一个方法叫做doFilter,它有3个实现类,分别是HtmlFilter(专门过滤js脚本的),SensitiveFilter(敏感关键字过滤,像falun功,反动言论这些),FaceFilter()。还有一个过滤器链类,FilterChain类,它也实现了Filter接口,它是一组过滤器的组合,可以理解成FilterChain是一个黑盒子,那它当然也就具备了Filter的功能。类图如下:
3.2、时序图如下:
3.3、关键类如下
3.3.1、Filter接口
package com.maizijf.test.zerenchain.mashibing;
/**
* Created by germmy on 17/3/3.
*/
public interface Filter {
public String doFilter(String str);
}
3.3.2、FilterChain类
package com.maizijf.test.zerenchain.mashibing;
import java.util.ArrayList;
import java.util.List;
/**
* Created by germmy on 17/3/3.
*/
public class FilterChain implements Filter {
private List<Filter> filterChainList=new ArrayList<Filter>();
public FilterChain addFilter(Filter filter){
filterChainList.add(filter);
return this;
}
public String doFilter(String str) {
String s=str;
for(Filter filter: filterChainList){
s=filter.doFilter(s);
}
return s;
}
}
3.3.3、HtmlFilter类
package com.maizijf.test.zerenchain.mashibing;
/**
* Created by germmy on 17/3/3.
*/
public class HtmlFilter implements Filter {
public String doFilter(String str) {
return str.replace("<","[").replace(">","]");
}
}
3.3.4、SensitiveFilter
package com.maizijf.test.zerenchain.mashibing;
/**
* Created by germmy on 17/3/3.
*/
public class SensitiveFilter implements Filter {
public String doFilter(String str) {
return str.replace("被教育","教育");
}
}
3.3.5、FaceFilter类
package com.maizijf.test.zerenchain.mashibing;
/**
* Created by germmy on 17/3/3.
*/
public class FaceFilter implements Filter {
public String doFilter(String str) {
return str.replace("笑","^_^");
}
}
3.3.6、JunitTest类
package com.maizijf.test.zerenchain.mashibing;
import org.junit.Test;
/**
* Created by germmy on 17/3/3.
*/
public class MashibingZerenlianTest {
@Test
public void testMashibingZerenlian(){
String str="大家好,我喜欢李成敏,笑;我是被教育了的野马,<script>";
MsgProcessor mp=new MsgProcessor();
FilterChain fc=new FilterChain();
String result=fc.addFilter(new HtmlFilter())
.addFilter(new SensitiveFilter())
.addFilter(new FaceFilter())
.doFilter(str);
System.out.println(result);
}
}