一、模式解析

  责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

  责任链模式的要点主要是:

  1、有多个对象共同对一个任务进行处理。

  2、这些对象使用链式存储结构,形成一个链,每个对象知道自己的下一个对象。

  3、一个对象对任务进行处理,可以添加一些操作后将对象传递个下一个任务。也可以在此对象上结束任务的处理,并结束任务。

  3、客户端负责组装链式结构,但是客户端不需要关心最终是谁来处理了任务。

二、模式代码

1、创建处理器接口

package chain.patten;
/**
* 责任链接口
* @author zjl
* @time 2016-2-11
*
*/
public abstract class Handler {
//下一级责任链
public Handler handler;
//设置下一级责任链
public void setSuccessor(Handler handler){
this.handler=handler;
}
public abstract void request(int request);
}

2、创建处理器对象1

package chain.patten;

public class ConcreteHandler1 extends Handler {
@Override
public void request(int request) {
if(request<10){
System.out.println("我是handler1,我处理了请求:"+request);
}else {
this.handler.request(request);
}
}
}

3、创建处理器对象2

package chain.patten;

public class ConcreteHandler2 extends Handler {
@Override
public void request(int request) {
if(request>10){
System.out.println("我是handler2,我处理了请求:"+request);
}else {
System.out.println("请求"+request+"没人能处理");
}
}
}

4、创建客户端

package chain.patten;

public class Client {
public static void main(String[] args) {
//创建处理器
Handler handler1=new ConcreteHandler1();
Handler handler2=new ConcreteHandler2();
//客户端创建处理器的关联,形成链
handler1.setSuccessor(handler2);
//创建任务,此处为一些数字,不同大小,处理器处理结果不同
int[] requests={4,10,59,2,16};
//调用处理器处理
for(int request:requests){
handler1.request(request);
}
}
}

5、执行结果

我是handler1,我处理了请求:4
请求10没人能处理
我是handler2,我处理了请求:59
我是handler1,我处理了请求:2
我是handler2,我处理了请求:16

三、应用场景

  在工作中,尤其是java web开发中,有两个地方明显使用责任链模式,一个是filter,一个是listener,filter的自定义在web开发中可以对web请求做各种处理和过滤,包括:对请求和相应的字符集处理、对跨站脚本攻击的过滤、获取客户端真实ip地址、获取客户证书、防止盗链等等,在此处,简单模拟责任链模式对请求的处理。

四、场景代码

1、过滤器接口

package chain.example;

public abstract class Filter {
//request 和response在真正的servlet中是对象,此处简化处理为string
public abstract void doFilter(String request,String response,FilterChain filterChain);
}

2、过滤器-处理字符集

package chain.example;

public class EncodeFilter extends Filter {

    @Override
public void doFilter(String request, String response, FilterChain filterChain) {
System.out.println("对request做utf-8编码");
filterChain.doFilter(request, response);
System.out.println("对response做utf-8编码");
} }

3、过滤器-处理xss攻击

package chain.example;

public class XssFilter extends Filter {

    @Override
public void doFilter(String request, String response, FilterChain filterChain) {
System.out.println("过滤request的xss内容");
filterChain.doFilter(request, response);
System.out.println("过滤response的xss内容");
} }

4、servlet接口,仅实现service接口

package chain.example;

public interface Servlet {
public void service(String request,String response);
}

5、定义一个servlet实现

package chain.example;

public class MainServlet implements Servlet {

    @Override
public void service(String request, String response) {
System.out.println(request);
//为response赋值
response="返回结果";
System.out.println(response);
} }

6、定义内部处理的filter链,链中保存真正filter的执行顺序,和servlet

package chain.example;

import java.util.ArrayList;
import java.util.List; public class FilterChain {
private int cursor;
public List<Filter> filters=new ArrayList<Filter>();
public Servlet servlet;
public void setServlet(Servlet servlet){
this.servlet=servlet;
}
public void addFilter(Filter filter){
this.filters.add(filter);
} public void doFilter(String request,String response){
if(cursor<filters.size()){
filters.get(cursor++).doFilter(request, response,this);
}else {
servlet.service(request, response);
}
}
}

7、客户端代码

package chain.example;

public class Client {
public static void main(String[] args) {
//定义filter
Filter encodeFilter=new EncodeFilter();
Filter xssFilter=new XssFilter();
FilterChain chain=new FilterChain();
chain.addFilter(encodeFilter);
chain.addFilter(xssFilter); //定义servlet
Servlet servlet=new MainServlet();
chain.setServlet(servlet);
chain.doFilter("发送请求", "");
}
}

8.、执行结果

对request做utf-8编码
过滤request的xss内容
发送请求
返回结果
过滤response的xss内容
对response做utf-8编码

五、实例说明

filter的责任链实现与责任链模式的标准代码有着一定的差距,它具有如下特点:

1、责任链的实现并不是链式结构,而是以一个FilterChain保存了所有责任链的引用,通过FilterChain的doFilter方法依次调用filter进行执行;

2、filter中同时也保存了FilterChain的引用,形成了一个双向引用;

3、FilterChain作为web容器的功能,由系统默认提供,我们无需关注其实现原理(注:代码中仅为可能实现的方式)。他依次将web.xml中的filter按照文件排放顺序进行调用执行。

由此我们思考,责任链模式的实现应该有多种形式,可以为责任链之间的互相链式引用,也可以为第三方集合中的顺序执行方式,在我所接触最广泛的系统中,对责任链进行如下使用:在执行真正交易时候,根据模板选择责任链,在配置文件中定义了一些列的Command,由chain方法将其转化为一个list的责任链,然后使用迭代器依次执行,对系统的传递请求进行一些列操作,格式为:

    <chain id="chainForRoleControlDV">
<commands>
<ref>RuleBasedDynamicViewCommand</ref>
<ref>roleControlCommand</ref>
<ref>validationCommand</ref>
<ref>ruleCommand</ref>
<ref>delegateCommand</ref>
<ref>${chain.monitor}</ref>
</commands>
</chain>

此种可以对请求进行登录控制,字段校验,权限控制,监控信息发送,验证码校验等一些列操作。这样只需要定义几个责任链可以完成对所有交易的区分控制。

[工作中的设计模式]责任链模式chain的更多相关文章

  1. C#设计模式-责任链模式(Chain of Responsibility Pattern)

    引子 一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程,软件开发中的异常处理流程,web请求处理流程等各种各样的流程,可以考虑使用责任链模式来实现.现在以请假流程为例,一般公 ...

  2. 23种设计模式--责任链模式-Chain of Responsibility Pattern

    一.责任链模式的介绍 责任链模式用简单点的话来说,将责任一步一步传下去,这就是责任,想到这个我们可以相当击鼓传花,这个是为了方便记忆,另外就是我们在项目中经常用到的审批流程等这一类的场景时我们就可以考 ...

  3. 设计模式-责任链模式Chain of Responsibility)

    一.定义 职责链模式是一种对象的行为模式.在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链 ...

  4. 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)

    原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...

  5. 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)

    责任链模式(Chain of Responsibility Pattern) 介绍为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求.将这些对象连成一条链,并沿着这条链传递该请求,直 ...

  6. 责任链模式-Chain of Responsibility(Java实现), 例2

    责任链模式-Chain of Responsibility 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 咱们在 ...

  7. 责任链模式-Chain of Responsibility(Java实现), 例1

    责任链模式-Chain of Responsibility, 例1 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. ...

  8. java 设计模式 -- 责任链模式

    设计模式 – 责任链模式 介绍: 责任链模式是一种动态行为模式,有多个对象,每一个对象分别拥有其下家的引用.连起来形成一条链.待处理对象则传到此链上,在此链进行传递,且待处理对象并不知道此会被链上的哪 ...

  9. Java与设计模式-责任链模式

    责任链模式属于行为型设计模式之中的一个,怎么理解责任链?责任链是能够理解成数个对象首尾连接而成,每个节点就是一个对象.每个对象相应不同的处理逻辑,直至有一个对象响应处理请求结束.这一种模式成为责任链模 ...

随机推荐

  1. <<< html5本地储存

    类似与Cookies,但由于Cookies储存量太小,大小也只有4-5KB的样子,html5的本地储存能存5M大小的数据 html5本地储存属性有,localStorage和sessionStorag ...

  2. 如何同时打开两个excel

    1. 打开一个excel1 2. 不要双击想要打开的excel2.右键excel应用的图标,选择excel2007. 3. 将excel2拖动到2所打开的新建excel中. 4. over.

  3. Yii rules常用规则

    public function rules() {     return array(         //必须填写         array('email, username, password, ...

  4. web前端历史的总结

    1.早期的前后一体,前端和后端是一个整体. 2.早期的后端mvc概念,前端只是后端mvc里面的视图层 (laravel就是mvc) 3.ajax技术改变了一切 2004年 Gmail 2005Goog ...

  5. 浅谈Android中Activity的生命周期

    引言 我想对于Android开发人员来说,Activity是再熟悉不过了,今天我们就来探讨下Activity的生命周期.熟悉的掌握Activity对于开发健壮的Android应用程序来说至关重要.下面 ...

  6. Html:form表单

    1:onsubmit 事件:会在表单中的确认按钮被点击时发生. <form action="" method="post" name="form ...

  7. IntersectionObserver API

    温馨提示:本文目前仅适用于在 Chrome 51 及以上中浏览. 2016.11.1 追加,Firefox 52 也已经实现. 2016.11.29 追加,Firefox 的人担心目前规范不够稳定,未 ...

  8. PHP session

    PHP Session PHP session 变量用于存储关于用户会话(session)的信息,或者更改用户会话(session)的设置.Session 变量存储单一用户的信息,并且对于应用程序中的 ...

  9. SQL中SET和SELECT赋值的区别

    最近的项目写的SQL比较多,经常会用到对变量赋值,而我使用SET和SELECT都会达到效果. 那就有些迷惑,这两者有什么区别呢?什么时候哪该哪个呢? 经过网上的查询,及个人练习,总结两者有以下几点主要 ...

  10. Node.js入门学习笔记(三)

    基于事件驱动的回调 这个问题不好回答,不过这是Node.js原生的工作方式.它是事件驱动的,这也是它为什么这么快的原因.你可以花一点时间阅读一下Felix Geisendörfer的大作 Unders ...