[工作中的设计模式]责任链模式chain
一、模式解析
责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
责任链模式的要点主要是:
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的更多相关文章
- C#设计模式-责任链模式(Chain of Responsibility Pattern)
引子 一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程,软件开发中的异常处理流程,web请求处理流程等各种各样的流程,可以考虑使用责任链模式来实现.现在以请假流程为例,一般公 ...
- 23种设计模式--责任链模式-Chain of Responsibility Pattern
一.责任链模式的介绍 责任链模式用简单点的话来说,将责任一步一步传下去,这就是责任,想到这个我们可以相当击鼓传花,这个是为了方便记忆,另外就是我们在项目中经常用到的审批流程等这一类的场景时我们就可以考 ...
- 设计模式-责任链模式Chain of Responsibility)
一.定义 职责链模式是一种对象的行为模式.在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链 ...
- 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)
原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...
- 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)
责任链模式(Chain of Responsibility Pattern) 介绍为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求.将这些对象连成一条链,并沿着这条链传递该请求,直 ...
- 责任链模式-Chain of Responsibility(Java实现), 例2
责任链模式-Chain of Responsibility 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 咱们在 ...
- 责任链模式-Chain of Responsibility(Java实现), 例1
责任链模式-Chain of Responsibility, 例1 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. ...
- java 设计模式 -- 责任链模式
设计模式 – 责任链模式 介绍: 责任链模式是一种动态行为模式,有多个对象,每一个对象分别拥有其下家的引用.连起来形成一条链.待处理对象则传到此链上,在此链进行传递,且待处理对象并不知道此会被链上的哪 ...
- Java与设计模式-责任链模式
责任链模式属于行为型设计模式之中的一个,怎么理解责任链?责任链是能够理解成数个对象首尾连接而成,每个节点就是一个对象.每个对象相应不同的处理逻辑,直至有一个对象响应处理请求结束.这一种模式成为责任链模 ...
随机推荐
- python下ssh的简单实现
python下的ssh都需要借助第三方模块paramiko来实现,在使用前需要手动安装. 一.python实现ssh (1) linux下的ssh登录 root@ubuntu:~# ssh morra ...
- RabbitMQ消息队列(一): Detailed Introduction 详细介绍
http://blog.csdn.net/anzhsoft/article/details/19563091 RabbitMQ消息队列(一): Detailed Introduction 详细介绍 ...
- windows系统在python3.5环境下安装mysql组件
折腾了一个多小时,终于把连接Mysql的模块装好了,由于我的环境是python3.5,Mysql官方支持到python3.4,后面google查到有pymysql模快支持python3.5,这个模块是 ...
- ActiveMQ支持的传输协议
------------------------------------------------------ ActiveMQ支持的client-broker通讯协议有:TCP.NIO.UDP.SSL ...
- [转]Oracle存在则更新,不存在则插入
原文:http://hi.baidu.com/mawf2008/item/eec8c7ad1c5be5ae29ce9da6 merge into a using bon (a.a=b.b)when m ...
- 如何修改Xampp中MySQL的root密码?
MySQL 的“root”用户默认状态是没有密码的,所以在 PHP 中您可以使用 mysql_connect("localhost","root"," ...
- MySQL Cluster 集群简介
简介 MySQL集群是一种在无共享架构(SNA,Share Nothing Architecture)系统里应用内存数据库集群的技术.这种无共享的架构可以使得系统使用低廉的硬件获取高的可扩展性. My ...
- sscanf提取字符串中的数据php
1.需求 理解sscanf的作用 2.例子 $str = "age:30 weight:60kg"; sscanf($str,"age:%d weight:%dkg&qu ...
- ftp服务配置文件记录
因为南京的客户死活要ftp服务而不是sftp,所以我作手用vsftp作为服务器,尝试在windows ftp软件登录进去,特记录vsftp的用法. 配置文件在/etc/vsftpd.conf 有如下代 ...
- PE440
一些证明,推荐复制入atom观看 首先我们考虑这个T(n)是什么,我们可以列出递归式: (definition:T) T(0) = 1 T(1) = 10 T(n) = 10*T(n-1) + T(n ...