美文网首页设计模式
责任链模式重构用户登录校验

责任链模式重构用户登录校验

作者: 童乐瑶 | 来源:发表于2017-09-23 10:15 被阅读49次

责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

适用场景

1、 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定 
2、 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
3、 可处理一个请求的对象集合应被动态指定

优缺点

优点:
1、责任链模式减低了发出命令的对象和处理命令的对象之间的耦合
2、它允许多与一个的处理者对象根据自己的逻辑来决定哪一个处理者最终处理这个命令。换言之,发出命令的对象只是把命令传给链结构的起始者,而不需要知道到底是链上的哪一个节点处理了这个命令。
3、在处理命令上,允许系统有更多的灵活性。哪一个对象最终处理一个命令可以因为由那些对象参加责任链、以及这些对象在责任链上的位置不同而有所不同。

缺点:
4、责任链模式要求链上所有的对象都继承自一个共同的父类或者实现一个共通的接口
5、所有责任开始都是从指定的接收者依次传递下去,运行中无法从中间开始传递

业务场景

进入实际业务流程前按照合规需求需要对用户进行一系列的校验,包括登录校验、是否在人组中、是否实名、是否绑卡等。

考虑到校验的顺序可能会重新调整、校验的逻辑随着业务场景的需求进行删减,故采用责任链模式进行重构。

校验接口

public interface CheckHandler {

    ApiErrorCode execute(CheckHandlerChain chain);
}

责任链

public class CheckHandlerChain implements CheckHandler {


    private ArrayList<CheckHandler> workList = new ArrayList<CheckHandler>();

    int index = 0;

    public ApiErrorCode execute(CheckHandlerChain chain) {
       
        if (index >= workList.size()) return ApiErrorCode.SUCCESS;

        CheckHandler work = workList.get(index);

        index++;

        return work.execute(chain);

    }

    //注册具体处理者到责任链的方法。
    public CheckHandlerChain setWork(CheckHandler work) {
        workList.add(work);
        return this;
    }
}
}

校验:登录校验

public class UserLoginHandler implements CheckHandler {

    //处理标识符,便于模拟业务逻辑。
    private String handleSwitch;

    private ApiErrorCode errorCode;

    public ApiErrorCode execute(CheckHandlerChain chain) {
        System.out.println("UserLoginHandler is working now......");

        //当标识符为“OFF”,本步骤不处理,直接返回
        if ("OFF".equals(handleSwitch)) {
            System.out.println("UserLoginHandler don't need to handle.");
            return chain.execute(chain);
        }

        // 处理过程
        errorCode = ApiErrorCode.SUCCESS;

        // 如果errorCode = SUCCESS,下发责任
        if (errorCode.getErrCode().equals(ApiErrorCode.SUCCESS.getErrCode())) {
            System.out.println(String.format("UserLoginHandler success. errorCode = [%s].\n", errorCode));
            return chain.execute(chain);
        } else {
            System.out.println(String.format("UserLoginHandler fail. errorCode = [%s].\n", errorCode));
            return errorCode;
        }
    }

    //处理标识符的getter和setter方法。
    public String getHandleSwitch() {
        return handleSwitch;
    }

    public void setHandleSwitch(String handleSwitch) {
        this.handleSwitch = handleSwitch;
    }

    public ApiErrorCode getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(ApiErrorCode errorCode) {
        this.errorCode = errorCode;
    }
}

校验:绑卡校验

public class UserCardBindHandler implements CheckHandler {

    //处理标识符,便于模拟业务逻辑。
    private String handleSwitch;

    private ApiErrorCode errorCode;

    public ApiErrorCode execute(CheckHandlerChain chain) {
        System.out.println("\nUserCardBindHandler is working now......");

        //当标识符为“OFF”,本步骤不处理,直接返回
        if ("OFF".equals(handleSwitch)) {
            System.out.println("UserCardBindHandler don't need to handle.");
            return chain.execute(chain);
        }

        // 处理过程
        errorCode = ApiErrorCode.USER_NOT_BIND_CARD;

        // 如果errorCode = SUCCESS,下发责任
        if (errorCode.getErrCode().equals(ApiErrorCode.SUCCESS.getErrCode())) {
            System.out.println(String.format("UserCardBindHandler success. errorCode = [%s].\n", errorCode));
            return chain.execute(chain);
        } else {
            System.out.println(String.format("UserCardBindHandler fail. errorCode = [%s].\n", errorCode));
            return errorCode;
        }
    }

    //处理标识符的getter和setter方法。
    public String getHandleSwitch() {
        return handleSwitch;
    }

    public void setHandleSwitch(String handleSwitch) {
        this.handleSwitch = handleSwitch;
    }

    public ApiErrorCode getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(ApiErrorCode errorCode) {
        this.errorCode = errorCode;
    }
}

校验:人组校验

public class UserGroupHandler implements CheckHandler {

    //处理标识符,便于模拟业务逻辑。
    private String handleSwitch;

    private ApiErrorCode errorCode;

    public ApiErrorCode execute(CheckHandlerChain chain) {
        System.out.println("UserGroupHandler is working now......");

        //当标识符为“OFF”,本步骤不处理,直接返回
        if ("OFF".equals(handleSwitch)) {
            System.out.println("UserGroupHandler don't need to handle.");
            return chain.execute(chain);
        }

        // 处理过程
        errorCode = ApiErrorCode.SUCCESS;

        // 如果errorCode = SUCCESS,下发责任
        if (errorCode.getErrCode().equals(ApiErrorCode.SUCCESS.getErrCode())) {
            System.out.println(String.format("UserGroupHandler success. errorCode = [%s].\n", errorCode));
            return chain.execute(chain);
        } else {
            System.out.println(String.format("UserGroupHandler fail. errorCode = [%s].\n", errorCode));
            return errorCode;
        }
    }

    //处理标识符的getter和setter方法。
    public String getHandleSwitch() {
        return handleSwitch;
    }

    public void setHandleSwitch(String handleSwitch) {
        this.handleSwitch = handleSwitch;
    }

    public ApiErrorCode getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(ApiErrorCode errorCode) {
        this.errorCode = errorCode;
    }
}

校验:用户实名校验

public class UserNameAuthHandler implements CheckHandler {

    //处理标识符,便于模拟业务逻辑。
    private String handleSwitch;

    private ApiErrorCode errorCode;

    public ApiErrorCode execute(CheckHandlerChain chain) {
        System.out.println("UserNameAuthHandler is working now......");

        //当标识符为“OFF”,本步骤不处理,直接返回
        if ("OFF".equals(handleSwitch)) {
            System.out.println("UserNameAuthHandler don't need to handle.");
            return chain.execute(chain);
        }

        // 处理过程
        errorCode = ApiErrorCode.USER_NOT_NAME_AUTH;

        // 如果errorCode = SUCCESS,下发责任
        if (errorCode.getErrCode().equals(ApiErrorCode.SUCCESS.getErrCode())) {
            System.out.println(String.format("UserNameAuthHandler success. errorCode = [%s].\n\n", errorCode));
            return chain.execute(chain);
        } else {
            System.out.println(String.format("UserNameAuthHandler fail. errorCode = [%s].\n\n", errorCode));
            return errorCode;
        }
    }

    //处理标识符的getter和setter方法。
    public String getHandleSwitch() {
        return handleSwitch;
    }

    public void setHandleSwitch(String handleSwitch) {
        this.handleSwitch = handleSwitch;
    }

    public ApiErrorCode getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(ApiErrorCode errorCode) {
        this.errorCode = errorCode;
    }
}

测试方法:

public class TestMain {

    public static void main(String[] args) {
        //实例化了四个具体处理对象
        UserLoginHandler userLoginHandler = new UserLoginHandler();
        UserGroupHandler userGroupHandler = new UserGroupHandler();
        UserNameAuthHandler userNameAuthHandler = new UserNameAuthHandler();
        UserCardBindHandler userCardBindHandler = new UserCardBindHandler();

        //仅仅为userNameAuthHandler设置了不需要处理的字段
        //意味着到了userNameAuthHandler对象处理的时候,直接跳过下发到另一个处理者那里了
        userNameAuthHandler.setHandleSwitch("OFF");

        //创建了一个责任链ch1,并以此绑定了具体处理者。
        //因此此责任链的工作顺序也是userLoginHandler->userGroupHandler->userNameAuthHandler
        CheckHandlerChain ch1 = new CheckHandlerChain();
        ch1.setWork(userLoginHandler).setWork(userGroupHandler).setWork(userNameAuthHandler);

        //创建了一个责任链对象ch2,并且绑定了userCardBindHandler为具体处理者
        CheckHandlerChain ch2 = new CheckHandlerChain();
        ch2.setWork(userCardBindHandler);

        //将责任链ch2绑定到ch1责任链的最后,也就是责任链ch1执行后还需要执行ch2的处理者
        ch1.setWork(ch2);

        //从责任链ch1开始执行
        ApiErrorCode result = ch1.execute(ch1);
        System.out.println("\nThe end result:" + result);
    }
}

运行结果

代码打包

https://github.com/lusalome/ChainOfResponsibilityTest

相关文章

网友评论

    本文标题:责任链模式重构用户登录校验

    本文链接:https://www.haomeiwen.com/subject/lkaqextx.html