[工作中的设计模式]责任链模式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与设计模式-责任链模式
责任链模式属于行为型设计模式之中的一个,怎么理解责任链?责任链是能够理解成数个对象首尾连接而成,每个节点就是一个对象.每个对象相应不同的处理逻辑,直至有一个对象响应处理请求结束.这一种模式成为责任链模 ...
随机推荐
- Web Service 中返回DataSet结果大小改进
http://www.cnblogs.com/scottckt/archive/2012/11/10/2764496.html Web Service 中返回DataSet结果方法: 1)直接返回Da ...
- [创业中, 寻求合作] 业务方向:车联网智能终端;APP蓝牙控制汽车;APP网络远程控制汽车 (联系电话:18503086002)
擅长领域 手机APP蓝牙控制汽车方案 手机APP网络远程控制汽车方案 手机APP与汽车车机的文件极速传输技术 车载OBD终端 (后装) 智能TBOX终端,Base on Linux,使用车规级硬件加密 ...
- Druid初步学习
Druid是一个JDBC组件,它包括三部分: DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体系. DruidDataSource 高效可管理的数据库连接池 ...
- 【06-23】js动画学习笔记01
<html> <head> <style> * { margin:0; padding:0; } #div1{ width:200px; height:200px; ...
- EntityFramework 数据库的迁移
第一步:在程序包管理器控制台里: Enable-Migrations -ProjectName EF所在的项目名称 第二步:运行后会在字段生成Migrations文件夹,Migrations-> ...
- Android 基础篇(二)
ADB进程 adb指令 adb install xxx.apk adb uninstall 包名 adb devices adb start-server adb kill-server adb sh ...
- Access应用笔记<四>-一个完整的自动化报表搭建过程
距离之前的三篇日志已经很久啦,今天终于完成了一个比较完整的自动化报表搭建过程 基于公司数据保密原则,样板就不放到网上来了,简单说一下背景: 这次access实现的功能包括: 1)为部门整体搭建了一个员 ...
- [Data Structure & Algorithm] 八大排序算法
排序有内部排序和外部排序之分,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.我们这里说的八大排序算法均为内部排序. 下图为排序 ...
- [Operate System & Algorithm] 页面置换算法
页面置换算法是什么?我们看一下百度百科对页面置换算法给出的定义:在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断.当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必 ...
- Ruby常用比较操作符
操作符 含义 == 测试值是否相等 ==== 用来比较case语句的目标和每个when从句的项 <=> 通用比较操作符. 根据接受者小于, 等于, 大于其参数, 返回-1, 0. 1 & ...