责任链模式
- gitee代码实现地址
1. 背景
- 需求: 实现过滤
- 需求2: 直接写好,不用修改的那种的过滤,就是可以从配置文件中读取的过滤器,然后加入到过滤器队列中。
- 需求3:可以在决定在哪里停止过滤,不用进行下一步的过滤。
- 需求4:在去的时候进行一个过滤,在回来的时候进行另一个过滤。
2.实现
- 链式编程实现filter
package chainOfResponsibility;
import com.sun.org.apache.bcel.internal.generic.GETFIELD;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
/*
*
* 实现方式0:在主类中进行过滤。
*
* 实现方式1,进行链式编程
* 实现方式2: 可以把链条加进来
* 实现方式3:sevlet中的过滤,递归的过程
* */
public class FilterChainI {
public static void main(String[] args) {
Message msg = new Message("你好 <script>, 大家都喜欢ssm");
FilterChain fc = new FilterChain();
fc.add(new HtmlFilter()).add(new SensitiveFilter());
fc.doFilter(msg);
System.out.println(msg.getMsg());
}
}
class Message {
String msg;
Message(String s) {
this.msg = s;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
}
interface Filter {
public void doFilter(Message s);
}
class HtmlFilter implements Filter{
@Override
public void doFilter(Message s) {
String t = s.getMsg().replaceAll("<", "[");
t = t.replaceAll(">", "]");
s.setMsg(t);
}
}
class SensitiveFilter implements Filter {
@Override
public void doFilter(Message s) {
String t = s.getMsg().replaceAll("ssm", "happy");
s.setMsg(t);
}
}
class FilterChain {
List<Filter> filters;
FilterChain() {
filters = new ArrayList<>();
}
public FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
public void doFilter(Message s) {
for (Filter f: filters) {
f.doFilter(s);
}
}
}
- 可以把链连接起来
package chainOfResponsibility;
import javafx.collections.transformation.FilteredList;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/*
*
*
* 实现方式2:链式添加
* */
public class FilterChainII {
public static void main(String[] args) {
Message msg = new Message("你好 <script>, 大家都喜欢ssm");
FilterChain2 fc = new FilterChain2();
fc.add(new HtmlFilter());
fc.add(new SensitiveFilter());
fc.doFilter(msg);
System.out.println(msg.getMsg());
}
}
class FilterChain2 {
List<Filter> filters = new ArrayList<>();
public void add(Filter f) {
filters.add(f);
}
public void doFilter(Message s) {
for (Filter f : filters) {
f.doFilter(s);
}
}
}
3. 实际应用
1. 过滤器
- 实现1: 使用数组实现顺序表
- 使用递归调用
- fc可以说是next指针,指向下一个需要执行的filter。
- 此处的fc是使用index进行实现的
- 优点分析
- 控制的流程放在了filterChain里面。
- 这样就算用户没有设置next,filterChain也可以保证安全。
- 细节
- index–;实现可以重复使用过滤器
- 把filterChain改成 filter next更容易理解
package chainOfResponsibility;
import java.util.ArrayList;
import java.util.List;
/*
*
* 经典servlet的实现版本
* */
public class FilterChainIV {
public static void main(String[] args) {
MyFilterChain fc = new MyFilterChain();
fc.add(new MyHtmlFilter()).add(new MySensitiveFilter());
MyResponse res = new MyResponse();
MyRequest req = new MyRequest();
fc.doFilter(req, res, fc);
System.out.println("req = " + req.msg);
System.out.println("resp = " + res.msg);
fc.doFilter(req, res, fc);
System.out.println("req = " + req.msg); // 进行二次过滤,或者进行别的过滤。
System.out.println("resp = " + res.msg);
}
}
class MyRequest {
String msg = "";
}
class MyResponse {
String msg = "";
}
interface MyFilter {
public void doFilter(MyRequest req, MyResponse resp, MyFilter next);
}
class MyFilterChain implements MyFilter{
List<MyFilter>filters = new ArrayList<>();
int index = 0;
public MyFilterChain add(MyFilter filter) {
filters.add(filter);
return this;
}
@Override
public void doFilter(MyRequest req, MyResponse resp, MyFilter next) {
if (index >= filters.size()) return ;
MyFilter filter = filters.get(index);
index++;
filter.doFilter(req, resp, next);
index--; // 进行回溯,否则没法进行重新过滤了
}
}
class MyHtmlFilter implements MyFilter{
@Override
public void doFilter(MyRequest req, MyResponse resp, MyFilter next) {
req.msg += "Req.htmlFilter-->";
next.doFilter(req, resp, next); // 如果从这里不进行递归调用,就不进行下一步处理了
resp.msg += "Resp.htmlFilter-->";
}
}
class MySensitiveFilter implements MyFilter{
@Override
public void doFilter(MyRequest req, MyResponse resp, MyFilter next) {
req.msg += "Req.sensitiveFilter-->";
next.doFilter(req, resp, next); // 有用户自己决定是否进行下一步的调用
resp.msg += "Resp.sensitiveFilter-->";
}
}
- 实现2:使用链表实现顺序表
package chainOfResponsibility.v5;
import java.io.FileNotFoundException;
import java.lang.reflect.Field;
/*
*
* 使用链表直接实现FilterChain
*
* 属性, Filter next
* 除了RuntimeException与其子类,以及错误(Error),其他的都是检查异常(绝对的大家族)。
*
*
* */
public class FilterChianI {
public static void main(String[] args) {
Filter htmlFilter = new HtmlFitler();
htmlFilter.setNext(new SesitiveFilter());
Requeset req = new Requeset();
Response res = new Response();
htmlFilter.doFilter(req, res);
System.out.println(req.msg);
System.out.println(res.msg);
}
}
abstract class Filter {
private Filter next;
public Filter setNext(Filter next){
this.next = next;
return this;
}
public abstract void doFilter(Requeset req, Response resp);
public Filter getNext() throws NullPointerException{
if (this.next != null) return this.next;
else throw new NullPointerException("没有设置next!!!请设置在调用");
}
}
class Requeset {
String msg = "";
}
class Response {
String msg = "";
}
class HtmlFitler extends Filter {
@Override
public void doFilter(Requeset req, Response resp) {
req.msg += "Req.htmlFilter->";
Filter nx = super.getNext();
nx.doFilter(req, resp);
resp.msg += "Resp.htmlFilter->";
}
}
class SesitiveFilter extends Filter {
@Override
public void doFilter(Requeset req, Response resp) {
req.msg += "Req.sensitiveFilter->";
//getNext().doFilter(req, resp); // 报错
resp.msg += "Resp.sensitiveFilter->";
}
}
- 此处设置如果没有设置next就抛出一个空指针异常,提醒用户只有在设置了之后才可以进行next的调用。
- 把Filter设置成一个链表,next就是Filter类型
- Fitler是一个抽象类。
- 当然可以实现链式的添加也可以实现链条的连接。
- 类图
2. 日志记录
需求: 我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。
-
菜鸟教程示例和第二种实现过滤器完全相同的思路,就不重复代码了。
-
类图(来自菜鸟教程)
4. 责任链模式分析
1. 定义
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
2. 类图
3. 优缺点分析
- 优点
- 允许动态的增加和删除职责,且由用户决定是否执行某种操作。
- 实现了被操作对象和操作的解耦。
- 缺点
- 系统复杂度提高,容易出错
- 影响性能,出现递归调用,容易造成栈溢出
4. 适用场景
- 由用户确定实现怎样的处理的流程。
- 不确定是否需要添加这种处理的情况。
- 把任务分解,大的任务分解成小步进行处理。
最后
- gitee代码实现地址
相关文章
暂无评论...