责任链模式(行为型)

责任链模式是一种行为设计模式,它允许在不明确指定接收者的情况下,将请求沿链传递,直到某个对象处理它。适用于多个对象可处理同一请求且处理者在运行时动态决定的场景。例如,Netty的ChannelOutboundHandler和Servlet的doFilter方法都应用了此模式。优点在于请求与处理解耦,链式结构灵活。然而,过长的链或循环引用可能导致性能下降或系统崩溃。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义

  1. 将链中的每个节点看作一个对象,每个节点负责的请求都不一样,并且会自动维护下一个节点对象
  2. 一个请求从链的首端发出时,会沿着链的路径依次传递给每个对象,直到有对象处理这个请求为止

适用场景

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

实例

public abstract class Hander<T> {
    protected Hander next;

    protected void next(Hander hander){
        this.next = hander;
    }

    public abstract void doHander(Member member);

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

        public Builder<T> addHander(Hander hander) {
            if (head == null) {
                this.head = this.tail = hander;
                return this;
            }
            this.tail.next(hander);
            this.tail = hander;
            return this;
        }

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

@Data
public class Member {
    private String loginName;
    private String loginPassword;
    private String roleName;
    private String emailName;

    public Member(String loginName, String loginPassword, String emailName) {
        this.loginName = loginName;
        this.loginPassword = loginPassword;
        this.emailName = emailName;
    }
    
}

public class ValidateHander extends Hander {
    @Override
    public void doHander(Member member) {
        if (StringUtils.isEmpty(member.getLoginName()) ||
                StringUtils.isEmpty(member.getLoginPassword())) {
            System.out.println("用户名和密码为空");
            return;
        }
        System.out.println("用户名和密码不为空,可以往下执行");
        next.doHander(member);
    }
}

public class LoginHander extends Hander {
    @Override
    public void doHander(Member member) {
        System.out.println("登录成功");
        member.setRoleName("管理员");

        next.doHander(member);
    }
}

public class EmailHander extends Hander {
    @Override
    public void doHander(Member member) {
        if (StringUtils.isEmpty(member.getEmailName())) {
            System.out.println("你的邮箱未注册");
            return;
        }
        System.out.println("你的邮箱已经注册,可以继续执行");
        next.doHander(member);
    }
}

public class AuthHander extends Hander {
    @Override
    public void doHander(Member member) {
        if(!"管理员".equals(member.getRoleName())) {
            System.out.println("你不是管理员没有操作权限");
            return;
        }

        if(!"666".equals(member.getEmailName())) {
            System.out.println("你未注册管理员邮箱没有操作权限");
            return;
        }
        System.out.println("允许操作");
    }
}

public class MemberService {
    public void login(String loginName, String loginPassword, String emailName) {
//        Hander loginHader = new LoginHander();
//        Hander authHader = new AuthHander();
//        Hander validateHander = new ValidateHander();
//
//        validateHander.next(loginHader);
//        loginHader.next(authHader);
//
//        validateHander.doHander(new Member(loginName,loginPassword));

        Hander.Builder builder = new Hander.Builder();
        builder.addHander(new ValidateHander())
                .addHander(new LoginHander())
                .addHander(new EmailHander())
                .addHander(new AuthHander());

        builder.build().doHander(new Member(loginName,loginPassword,emailName));

    }
}

public class Test {
    public static void main(String[] args) {
        MemberService memberService = new MemberService();
        memberService.login("hello","1","888");
    }
}

应用

  1. netty Channeloutboundhander
  2. servlet dofilter

优点

  1. 将请求与处理解耦
  2. 请求处理者,只需要处理感兴趣的节点,不感兴趣的转发给下一个节点
  3. 链式传递处理请求功能,不许关注链路结构 ,只需等待处理结果
  4. 链路结构灵活,动态的改变链路结构新增或者删减责任
  5. 易于扩展新的请求处理类(节点),符合开闭原则

缺点

  1. 责任链太长或者处理时间长,影响整体性能
  2. 对象节点存在循环引用时,造成死循环,系统崩溃
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值