work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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

Posted on 2019-01-07 21:45  work hard work smart  阅读(169)  评论(0编辑  收藏  举报

一、定义

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

1、为请求创建一个接收此次请求对象的链

2、类型:行为型

 

二、适用场景

一个请求的处理需要多个对象当中的一个或几个协作处理

 

三、有点

请求的发送者和接收者(请求的处理)解耦

责任链可以动态的组合

 

四、缺点

责任链太长或者处理时间过长,影像性能

责任链有可能过多



五、类图:

职责链模式的组成:
抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。
具体处理者(ConcreteHandle)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

六、实例:公司请病假,1天内,项目经理批准;2天内Senior PM批准; 大于两天,医院提供病例、假条
public abstract class LeaveBaseHandler
{
    protected LeaveBaseHandler successor;

    public LeaveBaseHandler getSuccessor()
    {
        return successor;
    }

    public void setSuccessor(final LeaveBaseHandler successor)
    {
        this.successor = successor;
    }

    public abstract void requestLeave(int days);
}

public class OneDayLeaveConcreteHandler extends LeaveBaseHandler
{
    @Override
    public void requestLeave(final int days)
    {
        if (days <= 1)
        {
            System.out.println("approve one day leave");
        }
        else
        {
            super.successor.requestLeave(days);
        }

    }

}

public class TwoDaysLeaveConcreteHandler extends LeaveBaseHandler
{
    @Override
    public void requestLeave(final int days)
    {
        if (days > 1 && days <= 2)
        {
            System.out.println("approve 2 days leave");
        }
        else
        {
            super.successor.requestLeave(days);
        }
    }
}

public class MoreThanTwoDaysConcreteHandler extends LeaveBaseHandler
{
    @Override
    public void requestLeave(final int days)
    {
        if (days > 2)
        {
            System.out.println("get the record for leave from hospital");
        }
    }
}

public class Client
{
    private static void requestLeave()
    {
        final LeaveBaseHandler oneDay = new OneDayLeaveConcreteHandler();
        final LeaveBaseHandler twoDays = new TwoDaysLeaveConcreteHandler();
        final LeaveBaseHandler moreThanTwoDays = new MoreThanTwoDaysConcreteHandler();
        oneDay.setSuccessor(twoDays);
        twoDays.setSuccessor(moreThanTwoDays);

        oneDay.requestLeave(1);
        oneDay.requestLeave(2);
        oneDay.requestLeave(3);
    }

    public static void main(final String[] args)
    {
        requestLeave();
    }
}

结果:
approve one day leave
approve 2 days leave
get the record for leave from hospital

如果职责链结构比较复杂,会产生很多的内存垃圾对象。

 

七、实例2

课程审核

1、创建批准者类

/**
 * 批准者 2019/1/7.
 */
public abstract class Approver {

    //责任链的核心是包含一个自己。 protected可以让子类获取到它
    protected Approver approver;


    //设置下一个批准者
    public  void setNextApprover(Approver approver){
        this.approver = approver;
    }

    //发布课程
    public abstract void deploy(Course course);
}

  

2、创建ArticleApprover 

public class ArticleApprover extends  Approver{
    @Override
    public void deploy(Course course) {
        if(StringUtils.isNotBlank(course.getArticle())){
            System.out.println(course.getName() + "含有Article,批准");
            if(approver != null){
                approver.deploy(course);
            }
        }else{
            System.out.println(course.getName() + "无Article,不批准,流程结束");
            return;
        }


    }
}

 

3、创建VideoApprover  

public class VideoApprover extends  Approver{
    @Override
    public void deploy(Course course) {
        if(StringUtils.isNotBlank(course.getVideo())){
            System.out.println(course.getName() + "含有Video,批准");
            if(approver != null){
                approver.deploy(course);
            }
        }else{
            System.out.println(course.getName() + "无Video,不批准,流程结束");
            return;
        }


    }
}

  

4、创建课程Course

public class Course {
    private String name;
    private String article;
    private String video;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getArticle() {
        return article;
    }

    public void setArticle(String article) {
        this.article = article;
    }

    public String getVideo() {
        return video;
    }

    public void setVideo(String video) {
        this.video = video;
    }

    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                ", article='" + article + '\'' +
                ", video='" + video + '\'' +
                '}';
    }
}

  

5、创建测试类

public class Test {
    public static void main(String[] args) {
        //审核员审核article
        Approver articleApprover = new ArticleApprover();
        //审核员审核video
        Approver videoApprover = new VideoApprover();

        Course course = new Course();
        course.setName("设计模式");
        course.setArticle("设计模式Article");
        course.setVideo("设计模式Video");

        articleApprover.setNextApprover(videoApprover);

        articleApprover.deploy(course);
    }
}

  

6、输出结果

 

 

 

八、在源码中的应用

1、javax.servlet.Filter

Servlet中的过滤器