【设计模式专题】责任链模式实战讲解
🍍每日推荐
🍖文章开始之前我想首先介绍一下牛客,以便没有使用过的小伙伴能够快速入手,牛客网是国内最大的算法、面试、招聘网站,涵盖了多种大厂面试真题以及题解,里面大佬云集,各种题目的解决方案层出不穷,绝对能让你大开眼界,而且牛客是你在人生中不同的阶段都能对你有所帮助的编程软件(完全免费),如果感兴趣可以访问注册一下
访问链接:牛客-国内最大的刷题网站
一 什么是责任链模式
责任链模式是一种让校验逻辑与业务解耦的一种设计模式,让每个节点都有自己的处理器,处理器去处理具体逻辑,并且每个节点都有对下一个节点的引用,类似于没有prev的单向链表,当前节点指向下一个节点。
当调用方法时,沿着预定的链路依次对每个节点进行处理,直到某个节点被终止或整条链路处理完成。
让调用方法者不用在意方法内的校验逻辑,只需要关注业务逻辑,让业务结构更加清晰。
二 什么时候使用责任链模式
比如一次请求,A条件不满足时立马return,B条件不满足时return,C条件不满足时return等等,所有的校验完成后开始进行业务逻辑。
第一 此时如果又发起了一个其他的请求那么又需要copy一份相同校验代码,完全没有进行复用。
第二 没有和业务解耦,代码中有60%都是校验代码,40%业务代码,头重脚轻。
如果我调用一个方法我肯定是不关心他校验的代码,我只关心它的业务代码,所以调用方法时需要观察大量无用代码,那么此时我们就可以使用责任链模式了。
三 实战
import lombok.Data;
/**
* @Author liuy
* @Description 用户信息
* @Date 2022/7/29 17:47
* @Version 1.0
*/
@Data
public class User {
private String userName;
private String password;
private Integer age;
}
import lombok.Data;
/**
* 责任链处理器抽象类
* @param <T>
*/
@Data
public abstract class Handler<T> {
protected Handler next;
//寻找下一个校验节点
private void next(Handler next) {
this.next = next;
}
public abstract void doHandler(User m);
public static class Builder<T> {
private Handler<T> head;
private Handler<T> tail;
public Builder<T> addHandler(Handler handler) {
if (this.head == null) {
this.head = this.tail = handler;
return this;
}
this.tail.next(handler);
this.tail = handler;
return this;
}
public Handler<T> build() {
return this.head;
}
}
}
import com.ruoyi.common.utils.StringUtils;
/**
* 登录校验处理器
*/
public class LoginHandler extends Handler {
@Override
public void doHandler(User member) {
if (StringUtils.isEmpty(member.getUserName()) ||
StringUtils.isEmpty(member.getPassword())) {
System.out.println("请填写用户名或密码");
return;
}
if (null != next) {
next.doHandler(member);
}
}
}
/**
* 年龄校验处理器
*/
public class AgeHandler extends Handler {
public AgeHandler() {
}
//建造者模式 再建造一些责任链中某个单位的子链路
public AgeHandler(Handler.Builder builder) {
builder.addHandler(new AgeMinHandler())
.addHandler(new AgeMaxHandler());
}
@Override
public void doHandler(User member) {
if (member.getAge() == null || member.getAge() == 0) {
System.out.println("请填写年龄");
return;
}
if (null != next) {
next.doHandler(member);
}
}
public static class AgeMinHandler extends Handler {
@Override
public void doHandler(User member) {
if (member.getAge() < 22 ) {
System.out.println("还没毕业 不要");
return;
}
if (null != next) {
next.doHandler(member);
}
}
}
public static class AgeMaxHandler extends Handler {
@Override
public void doHandler(User member) {
if (member.getAge() > 35) {
System.out.println("年龄太大 不要");
return;
}
if (null != next) {
next.doHandler(member);
}
}
}
}
测试
/**
* @Author liuy
* @Description 测试类
* @Date 2022/8/3 16:03
* @Version 1.0
*/
public class HandlerTest {
public static void main(String[] args) {
User member = new User();
member.setUserName("admin");
member.setPassword("123");
member.setAge(36);
Handler.Builder builder = new Handler.Builder();
//添加链路节点
builder.addHandler(new AgeHandler(builder))
.addHandler(new LoginHandler());
builder.build().doHandler(member);
}
}
结果
我们预设了责任链:LoginHandler——>AgeHandler,那么一个请求就会验证这个责任链一步步往后传递,要么被某个节点return终止,要么直至最后处理完成。
四、使用案例
JDK中的Filter,它是一个接口,类似我们的抽象Handler,它的子类实现其中的doFilter方法;
五、模式总结
5.1 优点
将请求和处理进行解耦;请求处理者只关注自己感兴趣的请求进行处理,对于不感兴趣的交给下一个节点处理;
具备链式传递处理能力,请求发送者不需要知道全局链路,符合迪米特法则(最少只是原则);
链路结构灵活,可以通过改变链路结构动态地增减责任,符合开闭原则;
5.2 缺点
责任链太长或者某个处理节点处理时间过长,会影响整体的性能;
如果处理节点存在循环引用,会造成死循环;
🍍每日推荐
🍖文章开始之前我想首先介绍一下牛客,以便没有使用过的小伙伴能够快速入手,牛客网是国内最大的算法、面试、招聘网站,涵盖了多种大厂面试真题以及题解,里面大佬云集,各种题目的解决方案层出不穷,绝对能让你大开眼界,而且牛客是你在人生中不同的阶段都能对你有所帮助的编程软件(完全免费),如果感兴趣可以访问注册一下
访问链接:牛客-国内最大的刷题网站
相关文章
- 设计模式-状态模式
- RabbitMQ的5种模式
- 设计模式实战应用之五:工厂方法模式
- 云计算设计模式(十六)——优先级队列模式
- 设计模式--创建性模式--单例
- Hadoop的伪分布式模式
- 《Android 源码设计模式解析与实战》——第2章,第2.3节单例模式的使用场景
- 《Android 源码设计模式解析与实战》——第2章,第2.6节单例模式的其他实现方式
- 《Android 源码设计模式解析与实战》——第2章,第2.7节Android源码中的单例模式
- 《Python编程实战:运用设计模式、并发和程序库创建高质量程序》—— 1.5 单例模式
- 《Python编程实战:运用设计模式、并发和程序库创建高质量程序》—— 2.5 外观模式
- 设计模式-策略模式与spring集成实战
- [js高手之路]设计模式系列课程-委托模式实战微博发布功能
- 深入Java设计模式之装饰模式
- 设计模式实战应用之二:观察者模式
- 设计模式(四)工厂方法模式
- 设计模式详解:Observer(观察者模式)
- 设计模式之单例模式简介
- 【设计模式】观察者模式
- 责任链模式
- 20行为型模式之中介者模式
- 设计模式(三): FACTORY工厂模式 -- 创建型模式
- 编程模式·观察者模式、事件通知、消息队列三者区别