设计模式之责任链模式

模式的定义与结构

责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

注意:责任链模式也叫职责链模式。
职责链模式主要包含以下角色。
抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理;理解责任链模式应当理解其模式,而不是其具体实现。责任链模式的独到之处是将其节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动起来。
结构图如下所示:

public abstract class Handler {

    protected Handler nextHandler;

    public void setNextHanlder(Handler successor) {
        this.nextHandler = successor;
    }

    public abstract void handleRequest(String request);

}
public class ConcreteHandlerA extends Handler {

    public void handleRequest(String request) {
        if ("requestA".equals(request)) {
            System.out.println(this.getClass().getSimpleName() + "deal with request: " + request);
            return;
        }
        if (this.nextHandler != null) {
            this.nextHandler.handleRequest(request);
        }
    }
}
public class ConcreteHandlerB extends Handler {

    public void handleRequest(String request) {
        if ("requestB".equals(request)) {
            System.out.println(this.getClass().getSimpleName() + "deal with request: " + request);
            return;
        }
        if (this.nextHandler != null) {
            this.nextHandler.handleRequest(request);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        handlerA.setNextHanlder(handlerB);
        handlerA.handleRequest("requestB");
    }
}

模式案例分析

案例:用户登录,非空验证---->登录验证---->权限验证,使用责任链模式实现热插拔权限控制。
分析:其判断逻辑是有先后顺序的。首先做非空判断,检查用户名密码是否有效,然后获得用户角色,最后判断用户是否拥有该操作权限。这样的检验性代码一般都是必不可少的,但是写在具体的业务代码中又显得非常臃肿,这时可以使用责任链模式,将这些检查步骤串联起来,既不影响代码美观,还可以使我们在编码时更加专注于某一个具体的业务逻辑处理。
程序结构设计:

案例代码

public abstract class Handler {

    protected Handler next;

    public void next(Handler next) {
        this.next=next;
    }

    public abstract void doHandler(Member member);
}
public class ValidateHandler extends Handler{
    @Override
    public void doHandler(Member member) {
        if(StringUtils.isEmpty(member.getLoginName()) ||
                StringUtils.isEmpty(member.getLoginPass())){
            System.out.println("用户名和密码为空");
            return;
        }
        System.out.println("用户名和密码校验非空,可以进行一下环节");
        next.doHandler(member);
    }
}
public class LoginHandler extends Handler {

    @Override
    public void doHandler(Member member) {
        member.setRoleName("管理员");
        System.out.println("登录成功,并获取用户权限信息,可以进行下一环节");
        next.doHandler(member);
    }
}
public class AuthHandler extends Handler{
    @Override
    public void doHandler(Member member) {
        if(!"管理员".equals(member.getRoleName())){
            System.out.println("您不是管理员,没有操作权限");
            return;
        }
        System.out.println("允许操作,责任链环节执行完毕");
    }
}
public class MemberService {

    public void login(Member member) {

        ValidateHandler validateHandler = new ValidateHandler();
        LoginHandler loginHandler = new LoginHandler();
        AuthHandler authHandler = new AuthHandler();

        validateHandler.next(loginHandler);
        loginHandler.next(authHandler);

        validateHandler.doHandler(member);
    }
}
public class Test {

    public static void main(String[] args) {
        MemberService service=new MemberService();
        service.login(new Member("hjp","PASS"));
    }
}

运行结果:

用户名和密码校验非空,可以进行一下环节
登录成功,并获取用户权限信息,可以进行下一环节
允许操作,责任链环节执行完毕

模式的应用场景总结

责任链模式通常在以下几种情况使用:
1、多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。
2、可动态指定一组对象处理请求,或添加新的处理者。
3、需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。

模式在开源框架中的应用--源码分析

参考

作者:薄荷加冰
出处:https://www.cnblogs.com/huangjianping/
版权:本文版权归作者和博客园共有
转载:本文以学习、研究和分享为主,欢迎转载和各类爬虫,但必须在文章页面明显位置给出原文链接。 如果文中有不妥或者错误的地方还望您指出,以免误人子弟。如果您有更好的建议,不如留言一起讨论,共同进步! 再次感谢您耐心的读完本篇文章。
原文地址:https://www.cnblogs.com/huangjianping/p/14971843.html