责任链模式
摘要:责任链模式,在实际应用中十分广泛,但是对于初级java工程师甚至是中级你都不一定用的好,这个模式顾名思义,就是将各种功能像链条穿起来,然后再统一执行。
一:案例:假如此时我们要多网站的关键词进行一个过滤,比如说过滤掉“黄色 ”,“敏感”,“广告”这三个词语。首先你要考虑,未来有可能我们会过滤更多的关键词语,可能不止这几个关键词。“开闭原则”,也就是说要将过滤器做成可以拓展的样子,这样才更好。分析好了下面我们来写代码,此时代码先不考虑责任链模式,先用传统思维实现功能。
- 定义一个类Content 模拟网站内容。
public class Content { //info 就是网站的内容,我们要过滤掉一些东西。 private String info; public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } }
- 网站内容类设计好了,接下来我们想的就是要定义过滤器了,遵从开闭原则,我们允许用户自定义拓展过滤器,也就是说过滤器处理类是一个父类,允许继承,所以说这个父类我们称为PostHandle ,我们可以把所有过滤器都用到的方法提取出来放入父类,这个方法就是Filter,方法的参数就是我们需要过滤的东西Content,具体过滤逻辑交给子类去实现。
public abstract class PostHandler { protected abstract void Filter(Content content); }
3.定义 一个广告过滤器 一个黄色关键词过滤器
/** * 广告处理器 */ public class AdHandler extends PostHandler { @Override protected void Filter(Content content) { String info = content.getInfo(); info = info.replace( "广告", "**" ); System.out.println( "过滤广告:》" + info ); //更新Content 中的info content.setInfo(info); } } /** * 涉黄处理器 */ public class YellowHandler extends PostHandler { @Override protected void Filter(Content content) { String info = content.getInfo(); info = info.replace( "涉黄", "**" ); System.out.println( "过滤涉黄" + info ); //更新Content 中的info content.setInfo(info); } } /** * 敏感词处理器 */ public class SensitiveWordsHandler extends PostHandler { @Override protected void Filter(Content content) { String info = content.getInfo(); info = info.replace("敏感词","**"); System.out.println("过滤敏感词"+info); //更新Content 中的info content.setInfo(info); } }
4. main方法
public class Main { public static void main(String[] args) { //content类中的info就是网站内容 Content content = new Content(); content.setInfo( "广告 。。。涉黄。。。敏感词" ); AdHandler adHandler = new AdHandler(); adHandler.Filter( content ); YellowHandler yellowHandler = new YellowHandler(); yellowHandler.Filter( content ); SensitiveWordsHandler sensitiveWordsHandler = new SensitiveWordsHandler(); sensitiveWordsHandler.Filter( content ); } } //输出结果: //过滤广告:》** 。。。涉黄。。。敏感词 //过滤涉黄** 。。。**。。。敏感词 //过滤敏感词** 。。。**。。。** //分析:当客户想要继续定义其他的过滤器的时候只需遵循一样的套路,即可。
二:上面代码其实可以更优雅一点,让我们分析一下,共同点就是每一次filter的时候都要在最后更新一下Content中的info信息,info信息后更后Content类将被传入下一个过滤器。以此类推一直传递,而这个一直传递的过程,就是链式的,那么我们时候可以将这个调用让代码体现出来?现在的过程是这样的。我们画图表示。
其实,我们可以在filter最后一行引入另一个一个方法,这个方法的作用就是将Content传递给下一个过滤器处理。下一个过滤器在接收到Content后,调用自己的Filter处理完成后,再将Contet传递给下一个过滤器,以此类推,在这个方法我们称为next,由于这个方法是公共的我们可以直接定义在父类中。Abstratc 父类改写如下。
public class Content {
private String info;
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
public abstract class PostHandler {
//postHandler 是下一个过滤器的引用,也就是说每一个过滤器都有三个属性:
//一个是 下一个过滤器的引用
//一个是filter负责处理content
//最后一个是next指针负责将content传递给,下一个过滤器的Filter中,下一个过滤器处理完了后再往后传递
//如此往后形成一条链
protected PostHandler postHandler;
protected PostHandler setPostHandler(PostHandler postHandler) {
this.postHandler = postHandler;
return postHandler;
}
//filter中更新content,紧接着调用next。这是抽象方法,由子类实现,这样子类继承父类后就拥有了,
// postHandler引用 ,filter方法 和next方法
protected abstract void Filter(Content content);
//filter被更新后的Content,在next中传递给下一个过滤器postHandler。
protected void next(Content content) {
if (postHandler != null) {
postHandler.Filter(content);
}
}
}
/**
* 广告处理器
*/
public class AdHandler extends PostHandler {
@Override
protected void Filter(Content content) {
String info = content.getInfo();
info = info.replace( "广告", "**" );
System.out.println( "过滤广告:》" + info );
content.setInfo( info );
next( content );
}
}
/**
* 敏感词处理器
*/
public class SensitiveWordsHandler extends PostHandler {
@Override
protected void Filter(Content content) {
String info = content.getInfo();
info = info.replace("敏感词","**");
System.out.println("过滤敏感词"+info);
content.setInfo( info );
next( content );
}
}
/**
* 涉黄处理器
*/
public class YellowHandler extends PostHandler {
@Override
protected void Filter(Content content) {
String info = content.getInfo();
info = info.replace( "涉黄", "**" );
System.out.println( "过滤涉黄" + info );
content.setInfo( info );
next(content);
}
}
public class Main {
public static void main(String[] args) {
Content content = new Content();
content.setInfo( "广告 。。。涉黄。。。敏感词" );
AdHandler adHandler = new AdHandler();
YellowHandler yellowHandler = new YellowHandler();
SensitiveWordsHandler sensitiveWordsHandler = new SensitiveWordsHandler();
adHandler.setPostHandler( yellowHandler ).setPostHandler( sensitiveWordsHandler );
adHandler.Filter( content );
}
}