责任链模式

1.定义xss

在责任链模式里,不少对象由每个对象对其下家的引用而链接起来造成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪个对象最终处理这个请求,这使得系统能够在不影响客户端的状况下动态地从新组织和分配责任。ide

 

2.问题和解决方案性能

击鼓传花是一种热闹而又紧张的饮酒游戏。在酒宴上宾客依次坐定位置,由一人击鼓,击鼓的地方与传花的地方是分开的,以示公正。开始击鼓时,花束就开始依次传递,鼓声一落,若是花束在某人手中,则该人就得饮酒。ui

  好比说,贾母、贾赦、贾政、贾宝玉和贾环是五个参加击鼓传花游戏的传花者,他们组成一个环链。击鼓者将花传给贾母,开始传花游戏。花由贾母传给贾赦,由贾赦传给贾政,由贾政传给贾宝玉,又贾宝玉传给贾环,由贾环传回给贾母,如此往复,以下图所示。当鼓声中止时,手中有花的人就得执行酒令。this

 击鼓传花即是责任链模式的应用。责任链多是一条直线、一个环链或者一个树结构的一部分。编码

 

3.结构.net

一个典型的对象结构可能以下图所示调试

code

抽象处理者角色(Handler:Approver):定义一个处理请求的接口,和一个后继链接(可选)。若是须要,接口能够定义出一个方法以设定和返回对下家的引用。这个角色一般由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操做。对象

具体处理者角色(ConcreteHandler:President):处理它所负责的请求,能够访问后继者,若是能够处理请求则处理,不然将该请求转给他的后继者。

客户类(Client):向一个链上的具体处理者ConcreteHandler对象提交请求

抽象处理者角色

public abstract class Handler {  
  
    /** 
     * 下一级责任链 
     */  
    protected Handler successor;  
  
    /** 
     * 示意处理请求的方法,虽然这个示意方法是没有传入参数的 但实际是能够传入参数的,根据具体须要来选择是否传递参数 
     */  
    public abstract void handleRequest();  
  
    /** 
     * 取值方法 
     */  
    public Handler getSuccessor() {  
        return successor;  
    }  
  
    /** 
     * 赋值方法,设置下一级责任链
     */  
    public void setSuccessor(Handler successor) {  
        this.successor = successor;  
    }  
  
}

具体处理者角色

public class ConcreteHandler extends Handler {  
    /** 
     * 处理方法,调用此方法处理请求 
     */  
    @Override  
    public void handleRequest() {  
        /** 
         * 判断是否有后继的责任对象 若是有,就转发请求给后继的责任对象 若是没有,则处理请求 
         */  
        if (getSuccessor() != null) {  
            System.out.println("放过请求");  
            getSuccessor().handleRequest();  
        } else {  
            System.out.println("处理请求");  
        }  
    }  
  
}

客户端类

public class Client {  
  
    public static void main(String[] args) {  
        // 组装责任链  
        Handler handler1 = new ConcreteHandler();  
        Handler handler2 = new ConcreteHandler();  
        handler1.setSuccessor(handler2);  
        // 提交请求  
        handler1.handleRequest();  
    } 
}

      能够看出,客户端建立了两个处理者对象,并指定第一个处理者对象的下家是第二个处理者对象,而第二个处理者对象没有下家。而后客户端将请求传递给第一个处理者对象。

  因为本示例的传递逻辑很是简单:只要有下家,就传给下家处理;若是没有下家,就自行处理。所以,第一个处理者对象接到请求后,会将请求传递给第二个处理者对象。因为第二个处理者对象没有下家,因而自行处理请求。

 

4.应用场景

过滤器接口

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

过滤器-处理字符集

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编码");
    }

}

过滤器-处理xss攻击

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内容");
    }

}

servlet接口,仅实现service接口

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

定义一个servlet实现

public class MainServlet implements Servlet {

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

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

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);
        }
    }
}

客户端代码

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("发送请求", "");
    }
}

处理结果

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

 

5.优缺点

优势

     下降耦合度 :该模式使得一个对象无需知道是其余哪个对象处理其请求。对象仅需知道该请求会被“正确”地处理。接收者和发送者都没有对方的明确的信息,且链中的对象不需知道链的结构。

     职责链可简化对象的相互链接 :    结果是,职责链可简化对象的相互链接。它们仅需保持一个指向其后继者的引用,而不需保持它全部的候选接受者的引用。

     加强了给对象指派职责( R e s p o n s i b i l i t y )的灵活性 :当在对象中分派职责时,职责链给你更多的灵活性。你能够经过在运行时刻对该链进行动态的增长或修改来增长或改变处理一个请求的那些职责。你能够将这种机制与静态的特例化处理对象的继承机制结合起来使用。

增长新的请求处理类很方便

缺点

      不能保证请求必定被接收。既然一个请求没有明确的接收者,那么就不能保证它必定会被处理 —该请求可能一直到链的末端都得不处处理。一个请求也可能因该链没有被正确配置而得不处处理。

     系统性能将受到必定影响,并且在进行代码调试时不太方便;可能会形成循环调用。

 

6.总结

      在职责链模式里,不少对象由每个对象对其下家的引用而链接起来造成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪个对象最终处理这个请求,这使得系统能够在不影响客户端的状况下动态地从新组织链和分配责任。

      职责链模式的主要优势在于能够下降系统的耦合度,简化对象的相互链接,同时加强给对象指派职责的灵活性,增长新的请求处理类也很方便;其主要缺点在于不能保证请求必定被接收,且对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到必定影响,并且在进行代码调试时不太方便。

参考:

http://blog.csdn.net/m13666368773/article/details/7702368

http://blog.csdn.net/hguisu/article/details/7547231

相关文章
相关标签/搜索