责任链模式

一、责任链模式介绍

1、定义与类型

为请求创建一个接收此次请求对象的链
类型:行为型

2、适用场景

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

3、优点

请求的发送者和接收者(请求的处理)解耦
责任链可以动态组合

4、缺点

责任链太长或者处理时间过长,影响性能
责任链有可能过多

5、相关设计模式

责任链模式和状态模式
责任链模式中,各个对象并不指定下一个处理对象者是谁,只有客户端来设置顺序和元素,直到被某个责任链元素处理或者整个责任链结束。
状态模式是让每个状态对象知道下一个状态对象是谁,在编译时就设定好了。

二、代码示例

模拟场景:发布课程,课程中需要含有手记和视频,才能批准;
第一步,先检查手记,不为空才能批准,否则不批准
第二步,再检查视频,不为空才能批准,否则不批准

课程类:

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

    public Course(String name, String article, String video) {
        this.name = name;
        this.article = article;
        this.video = video;
    }

    public Course() {
    }
}

1、v1版本(Appover):

处理抽象类:

public abstract class Appover {
    protected Appover nextAppover;

    public void setNextAppover(Appover nextAppover){
        this.nextAppover = nextAppover;
    }

    public abstract void deploy(Course course);
}

手记处理类:

public class ArticleAppover extends Appover {
    @Override
    public void deploy(Course course) {
        if (StringUtil.isNotEmpty(course.getArticle())){
            System.out.println(course.getName() + " 含有手记, 批准");
            if (nextAppover != null){
                nextAppover.deploy(course);
            } else  {
                System.out.println("链条结束");
            }
        } else {
            System.out.println(course.getName() + " 不包含有手记, 不批准,流程结束");
            return;
        }
    }
}

视频处理类:

public class VideoAppover extends Appover {
    @Override
    public void deploy(Course course) {
        if (StringUtil.isNotEmpty(course.getVideo())){
            System.out.println(course.getName() + " 含有视频, 批准");
            if (nextAppover!= null){
                nextAppover.deploy(course);
            } else  {
                System.out.println("链条结束");
            }
        } else {
            System.out.println(course.getName() + " 不包含有视频, 不批准,流程结束");
            return;
        }
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        Appover articleAppover = new ArticleAppover();
        Appover videoAppover = new VideoAppover();
        articleAppover.setNextAppover(videoAppover);

        Course course1 = new Course("责任链模式讲解", "手记", "视频");
        articleAppover.deploy(course1);

        Course course2 = new Course();
        course2.setName("设计模式");
        articleAppover.deploy(course2);
    }
}

输出:
责任链模式讲解 含有手记, 批准
责任链模式讲解 含有视频, 批准
链条结束
设计模式 不包含有手记, 不批准,流程结束

2、v2版本(Handler),(推荐,使用起来更加灵活):

处理抽象类:

public abstract class AbstractHandler {
    abstract void doHandler(HandlerChainContext handlerChainContext, Course course); // handler方法
}

处理类上下文(对处理类进行包装):

/**
 * handler上下文,主要负责维护链,和链的执行
 */
public class HandlerChainContext {
    HandlerChainContext next; // 下一个节点
    AbstractHandler handler;

    public HandlerChainContext(AbstractHandler handler) {
        this.handler = handler;
    }

    void handler(Course course) {
        this.handler.doHandler(this, course);
    }

    /**
     * 继续执行下一个
     */
    void runNext(Course course) {
        if (this.next != null) {
            this.next.handler(course);
        } else {
            System.out.println("链条结束");
        }
    }
}

手记处理类:

public class ArticleHandler extends AbstractHandler{
    @Override
    void doHandler(HandlerChainContext handlerChainContext, Course course) {
        if (StringUtil.isNotEmpty(course.getArticle())){
            System.out.println(course.getName() + " 含有手记, 批准");
            // 继续执行下一个
            handlerChainContext.runNext(course);
        } else {
            System.out.println(course.getName() + " 不包含有手记, 不批准,流程结束");
            return;
        }
    }
}

视频处理类:

public class VideoHandler extends AbstractHandler {
    @Override
    void doHandler(HandlerChainContext handlerChainContext, Course course) {
        if (StringUtil.isNotEmpty(course.getVideo())){
            System.out.println(course.getName() + " 含有视频, 批准");
            // 继续执行下一个
            handlerChainContext.runNext(course);
        } else {
            System.out.println(course.getName() + " 不包含有视频, 不批准,流程结束");
            return;
        }
    }
}

链路类:

public class PipelineChain {
    /**
     * 初始化的时候造一个head,作为责任链的开始,但是并没有具体的处理
     * 目的就是启动下一个handler
     */
    public HandlerChainContext head = new HandlerChainContext(new AbstractHandler() {
        @Override
        void doHandler(HandlerChainContext handlerChainContext, Course course) {
            handlerChainContext.runNext(course);
        }
    });

    public void requestProcess(Course course) {
        this.head.handler(course);
    }

    public void addLast(AbstractHandler handler) {
        HandlerChainContext context = head;
        while (context.next != null) {
            context = context.next;
        }
        context.next = new HandlerChainContext(handler);
    }
}

测试类:

public class Test {

    public static void main(String[] args) {
        PipelineChain pipelineChain = new PipelineChain();

        // 优点:此处的 ArticleHandler 和 VideoHandler 不需要直接产生关联
        // 即可以直接在中间增加其他 Handler
        pipelineChain.addLast(new ArticleHandler());
        pipelineChain.addLast(new VideoHandler());

        Course course1 = new Course("责任链模式讲解", "手记", "视频");
        // 发起请求
        pipelineChain.requestProcess(course1);


        Course course2 = new Course();
        course2.setName("设计模式");
        // 发起请求
        pipelineChain.requestProcess(course2);

    }
}

输出:
责任链模式讲解 含有手记, 批准
责任链模式讲解 含有视频, 批准
链条结束
设计模式 不包含有手记, 不批准,流程结束

三、源码示例

Servlet中的Filter



posted @ 2020-08-20 09:13  weixiaokun  阅读(293)  评论(0编辑  收藏  举报