设计模式——个人学习之责任链模式

简介

对于责任链模式,我相信很多人或多或少都是接触过了,或者在阅读JDK的源码过程中也见到过,比如JDK中的Filter就是通过责任链的模式来实现。在我们的实际开发过程中,我们可能遇到很多if…else…,这些判断复杂而难以处理,这样会造成我们的代码极其臃肿难以阅读,对于这样的代码我们可以提取出来,利用责任链模式重构。

定义

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

优点

  • 代码的可阅读性增强,结构清晰明了
  • 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则
  • 每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则

缺点

  • 如果链条较长,阅读起来比较繁琐,系统性能也将受到一定影响
  • 可能由于设计和人为失误,容易造成循环链条

结构

责任链模式主要包含三个角色:

  1. 抽象处理者(Handler)角色:定义一个抽象方法,同时需要定义一个后继处理角色方法。
  2. 具体处理者(Concrete Handler)角色:实现抽象处理方法的具体细节,处理完毕需要根据处理结果来判断是否交给后续处理角色,同时也可以扩展为是否在当前角色处理等等。
  3. 客户类(Client)角色:维护具体处理角色关系,调用方法。

在这里插入图片描述

示例一

抽象类:

package com.example.demo.design.responsibility.simple;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 21:48
 * @description: 抽象角色类,提供一个抽象审批方法
 */
public abstract class Role {
    protected Role role;

    /*
        这个方法主要是来提供链条的
     */
    public void setNextRole(Role role) {
        this.role = role;
    }

    /*
        提供一个抽象审批方法
     */
    public abstract boolean approve();
}

具体角色类:

package com.example.demo.design.responsibility.simple;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 21:49
 * @description: 组长:继承角色获得审批权限
 */
public class GroupLeader extends Role{

    @Override
    public boolean approve() {
        System.out.println("组长审批!");
        //经过某些处理组长通过(这里当然也可以不通过)
        boolean flag = true;
        if(flag && role != null){
            return role.approve();
        }
        return flag;
    }
}
package com.example.demo.design.responsibility.simple;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 22:18
 * @description: 经理:继承角色获得审批权限
 */
public class Manager extends Role{
    @Override
    public boolean approve() {
        System.out.println("经理审批!");
        //经过某些处理经理通过(这里当然也可以不通过)
        boolean flag = true;

        //这里加上flag主要是为了判断,当然实际是不需要加的,因为如果上面某些判断结果为false那可能直接返回了
        if(flag && role != null){
            return role.approve();
        }
        return flag;
    }
}
package com.example.demo.design.responsibility.simple;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 22:23
 * @description: 财务:继承角色获得审批权限
 */
public class Finance extends Role{
    @Override
    public boolean approve() {
        System.out.println("财务审批!");
        //经过某些处理经理通过(这里当然也可以不通过)
        boolean flag = true;

        return flag;
    }
}

客户端:

package com.example.demo.design.responsibility.simple;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 22:28
 * @description: 测试类
 */
public class Test {
    public static void main(String[] args) {
        Role groupLeader = new GroupLeader();
        Role manager = new Manager();
        Role finance = new Finance();

        //将审批关系关联好
        manager.setNextRole(finance);
        groupLeader.setNextRole(manager);
        //调用第一个角色审批
        boolean approve = groupLeader.approve();
        System.out.println(approve);
    }
}

结果:
组长审批!
经理审批!
财务审批!
true

示例二

接口:

package com.example.demo.design.responsibility.advanced;

/**
 * 接口,定义一个方法
 */
public interface Role {
    /**
     * 方法说明
     * @param request 处理的请求
     * @param response  处理的结果
     * @param chainRole 这个参数很重要,它是责任链执行的发起者,在整个流程中,他控制流程
     * @return
     */
    public boolean approve(Request request,Response response,ChainRole chainRole);
}

具体角色类:

package com.example.demo.design.responsibility.advanced;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 23:39
 * @description:
 */
public class GroupLeader implements Role{
    @Override
    public boolean approve(Request request, Response response, ChainRole chainRole) {
        //处理请求结果
        request.setRequestStr(request.getRequestStr() + "GroupLeader Request ; ");
        //调用chainRole的excute方法,根据方法内的index,逐层升入
        chainRole.excute(request,response);
        response.setResponseStr(response.getResponseStr() + "GroupLeader Response ; ");
        return true;
    }
}

package com.example.demo.design.responsibility.advanced;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 23:39
 * @description:
 */
public class Manager implements Role{
    @Override
    public boolean approve(Request request, Response response, ChainRole chainRole) {
        request.setRequestStr(request.getRequestStr() + "Manager Request ; ");
        chainRole.excute(request,response);
        response.setResponseStr(response.getResponseStr() + "Manager Response ; ");
        return true;
    }
}

package com.example.demo.design.responsibility.advanced;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 23:39
 * @description:
 */
public class Finance implements Role{
    @Override
    public boolean approve(Request request, Response response, ChainRole chainRole) {
        request.setRequestStr(request.getRequestStr() + "Finance Request ; ");
        chainRole.excute(request,response);
        response.setResponseStr(response.getResponseStr() + "Finance Response ; ");
        return true;
    }
}

责任链维护类:

package com.example.demo.design.responsibility.advanced;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 23:32
 * @description: 这个类至关重要,这个类是实际调用各个具体责任类
 */
public class ChainRole {
    //list里面存放具体责任类对象
    List<Role> list = new ArrayList<>();
    //index从0开始,当所有具体责任类完成操作,它控制了这个链条结束标识(仔细阅读这个链条,你可以发现它是一个递归)
    int index = 0;

    //增加具体责任类方法,因为list是有序的,所有可以根据index,逐个执行,保证顺序
    public ChainRole add(Role role){
        list.add(role);
        return this;
    }

    //核心方法:他主要是判断这个递归深度,控制其返回;同时它也是开始的起点
    public boolean excute(Request request,Response response){
        if(list.size() == index)
        {
            return false;
        }
        //这个role在每次外部调用excute方法后都是根据当前index值来获得的具体责任类
        Role role = list.get(index);
        index++;
        return role.approve(request,response,this);
    }

}

客户端

package com.example.demo.design.responsibility.advanced;

/**
 * @author: sunzhinan
 * @create: 2020-07-31 23:43
 * @description:
 */
public class Test {

    public static void main(String[] args) {
        Request request = new Request();
        request.setRequestStr("请求来了 : ");
        Response response = new Response();
        response.setResponseStr("返回来了 : ");

        ChainRole chainRole = new ChainRole();
        chainRole.add(new GroupLeader());
        chainRole.add(new Manager());
        chainRole.add(new Finance());

        chainRole.excute(request,response);

        System.out.println(request.getRequestStr());
        System.out.println(response.getResponseStr());
    }
}

结果:

请求来了 : GroupLeader Request ; Manager Request ; Finance Request ;
返回来了 : Finance Response ; Manager Response ; GroupLeader Response ;

实际应用

在我们的熟悉的框架中,我们也能发现它的身影,比如 Struts2 的拦截器、JSP 和 Servlet 的 Filter。在实际项目开发中,我们对于登录过程的权限校验,可能要进行不同级别层级的权限校验,那么我们可以通过责任链来实现。因此总结起来,对于一些具用共同目标的,且可以分成不同职责,同时不同职责的类可以重复使用的情境下,我们可以选择这种设计模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值