责任链模式

一、责任链模式

1、定义

责任链模式(Chain of Responsibility Pattern),是指将链中每一个节点都看作一个对象,每个节点处理的请求均不同,且内部自动维护下一个节点对象。当一个请求从链式的首端发出时,会沿着责任链预设的路径依次传递到每一个节点对象,直到被链中的某个对象处理为止,属于行为型设计模式。

责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与处理。

2、结构

(1)模式的结构

主要角色如下:

  • 抽象处理者(Handler):定义一个请求处理的方法,并维护一个下一处理节点的 Handler对象的引用。
  • 具体处理者(ConcreteHandler):对请求进行处理,如果不感兴趣,则进行转发到它的下一个节点。

3、优缺点

优点:

  • 将请求与处理解耦。
  • 请求处理者只需关注自己感兴趣的请求进行处理即可,对于不感兴趣的请求,直接转发给下一个节点处理。
  • 链路结构灵活,可以通过盖帘链结构动态地新增或删减责任。
  • 易扩展,符合开闭原则

缺点:

  • 责任链太长或者处理时间太长,会影响整体性能。
  • 如果节点对象存在循环引用,则会造成死循环,导致系统崩溃。

4、使用场景

  • 多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。
  • 在不明确指定接收者的情况下,向多个对象中的一个提交请求。
  • 可动态指定一组对象处理请求。

5、在框架源码中使用

  • Java中的 Filter类。
  • Spring Security或者Shiro都用到责任链模式。

二、模式的通用实现

代码如下:

public class ChainOfResponsibilityPattern {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();

        handlerA.setNextHandler(handlerB);

        handlerA.doHandle("A");
        System.out.println("----------");
        handlerA.doHandle("B");
        System.out.println("----------");
        handlerA.doHandle("C");
    }
}

//抽象处理者
abstract class Handler{
    // 下一个节点对象引用
    protected Handler nextHandler;

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

    public abstract void doHandle(String request);
}

// 具体处理者
class ConcreteHandlerA extends Handler{

    @Override
    public void doHandle(String request) {
        if("A".equals(request)){
            System.out.println("ConcreteHandlerA 处理请求");
            return;
        }
        if(this.nextHandler != null){
            this.nextHandler.doHandle(request);
        }
    }
}

class ConcreteHandlerB extends Handler{

    @Override
    public void doHandle(String request) {
        if("B".equals(request)){
            System.out.println("ConcreteHandlerB 处理请求");
            return;
        }
        if(this.nextHandler != null){
            this.nextHandler.doHandle(request);
        }
    }
}

在这里插入图片描述

三、模式的应用实例

已授权登录校验为例。

@Data
public class User {
	private String username;

	private String pazzWord;

	private String roleName;
}

示例一

责任链模式编写:

(1)抽象处理类

public abstract class WebHandler {
    protected WebHandler chain;

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

    public abstract void doHandle(User user);
}

(2)具体处理类

public class ValidateWebHandler extends WebHandler{
    @Override
    public void doHandle(User user) {
        if(user == null){
            System.out.println("用户为空");
            return;
        }
        if(StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPazzWord())){
            System.out.println("用户名或者密码为空");
            return;
        }
        System.out.println("用户信息校验成功。向下一个执行");
        this.chain.doHandle(user);
    }
}

public class LoginWebHandler extends WebHandler{
    @Override
    public void doHandle(User user) {
        System.out.println("查询数据库,用户登录成功。");
        user.setRoleName("admin");
        System.out.println("查询用户角色,向下一个执行");
        this.chain.doHandle(user);
    }
}

public class AuthWebHandler extends WebHandler{
    @Override
    public void doHandle(User user) {
        if("admin".equals(user.getRoleName())){
            System.out.println("管理员上线,允许进行全部操作");
            return;
        }else{
            System.out.println("普通用户上线,正常权限进行操作");
        }
    }
}

(3)测试

    public static void main(String[] args) {
        WebHandler validateWebHandler = new ValidateWebHandler();
        WebHandler loginWebHandler = new LoginWebHandler();
        WebHandler authWebHandler = new AuthWebHandler();

        validateWebHandler.next(loginWebHandler);
        loginWebHandler.next(authWebHandler);

        User user = new User();
        user.setUsername("赵云");
        user.setPazzWord("123456");
        validateWebHandler.doHandle(user);
    }

在这里插入图片描述

示例二

针对复杂结构的责任链组装。我们可以结合建造者模式一起使用。

(1)抽象处理类

public abstract class WebHandler2<T> {
	protected WebHandler2 chain;

	private void next(WebHandler2 Handler) {
		this.chain = Handler;
	}

	public abstract void doHandle(User user);

	public static class Builder<T> {
		private WebHandler2<T> head;
		private WebHandler2<T> tail;

		public Builder<T> addWebHandler(WebHandler2<T> webHandler2) {
			if (this.head == null) {
				this.head = this.tail = webHandler2;
				return this;
			}
			this.tail.next(webHandler2);
			this.tail = webHandler2;
			return this;
		}

		public WebHandler2<T> build() {
			return this.head;
		}
	}
}

(2)具体处理类

public class ValidateWebHandler extends WebHandler2{
    @Override
    public void doHandle(User user) {
        if(user == null){
            System.out.println("用户为空");
            return;
        }
        if(StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPazzWord())){
            System.out.println("用户名或者密码为空");
            return;
        }
        System.out.println("用户信息校验成功。向下一个执行");
        this.chain.doHandle(user);
    }
}

public class LoginWebHandler extends WebHandler2{
    @Override
    public void doHandle(User user) {
        System.out.println("查询数据库,用户登录成功。");
        user.setRoleName("admin");
        System.out.println("查询用户角色,向下一个执行");
        this.chain.doHandle(user);
    }
}

public class AuthWebHandler extends WebHandler2{
    @Override
    public void doHandle(User user) {
        if("admin".equals(user.getRoleName())){
            System.out.println("管理员上线,允许进行全部操作");
            return;
        }else{
            System.out.println("普通用户上线,正常权限进行操作");
        }
    }
}

(3)测试

    public static void main(String[] args) {
        WebHandler2.Builder<Object> webHandler2 = new WebHandler2.Builder<>();
        webHandler2.addWebHandler(new ValidateWebHandler2())
                .addWebHandler(new LoginWebHandler2())
                .addWebHandler(new AuthWebHandler2());

        User user = new User();
        user.setUsername("赵子龙");
        user.setPazzWord("123456");
        webHandler2.build().doHandle(user);
    }

– 求知若饥,虚心若愚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值