【设计模式】之责任链模式

时间:2024-05-03 07:07:47

系列文章目录

  • 【设计模式】之策略模式


文章目录

系列文章目录

前言

一、什么是责任链模式

二、有什么使用场景呢

三、如何使用责任链模式

总结


前言

上次我们了解了设计模式中的策略模式,今天我们继续学习责任链模式。????


一、什么是责任链模式

为请求创建了一个接受者对象的链。为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。举个通俗易懂的例子,就是我们撸串的时候,我们一般都是从签的上方一个一个往下撸的,责任链模式就跟这个类似。

二、有什么使用场景呢

责任链模式因为可以灵活地配置处理者的顺序和数量,而不需要修改客户端代码。所以责任链模式在项目实战中用处广泛。

  • JDK中的异常处理机制就使用了责任链模式。当某个方法抛出异常时,首先会在方法内部寻找try-catch块来捕获异常,如果没有找到,就会将异常向上一层抛出,直至找到合适的catch块处理。
  • Spring框架中的拦截器链机制也使用了责任链模式。拦截器链是通过将各个拦截器按照一定的顺序连接起来形成一个链条,在请求处理过程中按顺序调用每个拦截器的相应方法来完成一系列操作。

责任链模式还可以用于处理日志记录、用户权限验证等场景。

三、如何使用责任链模式

我给大家举一个简单的例子,如:大学请假流程,我就以 院长-->导员-->任课老师这个流程来给大家解释。

首先,我们定义一个请假的接口,当然,用抽象类也阔以。

/**
* 说明: 请假接口
*/

public interface TakeLeave {
    boolean doTakeLeave(User user);
}

然后呢,院长、导员、任课老师,分别去实现这个接口

/*院长*/
@Order(0)
@Component
public class deanHandler implements TakeLeave{
    @Override
    public boolean doTakeLeave(User user) {
        if (user.getReason() == null || user.getReason().isEmpty()) {
            System.out.println("院长:没有请假理由,拒绝请假!");
            return false;
        }
        System.out.println("院长:已审核,提交给导员。");
        return true;

    }
}
/*导员*/
@Component
@Order(100)
public class GuideHandler implements TakeLeave{
    @Override
    public boolean doTakeLeave(User user) {
        if (!user.getReason().contains("事") && !user.getReason().contains("病")) {
            System.out.println("导员:理由不充分,拒绝请假!");
            return false;
        }
        System.out.println("导员:已审核,提交给任课老师。");
        return true;
    }
}
/*任课老师*/
@Component
@Order(200)
public class LecturerHandler implements TakeLeave{
    @Override
    public boolean doTakeLeave(User user) {
        System.out.println("任课老师:已同意学生请假。");
        return true;
    }
}

大家可以注意到,我Order里面优先级的数字设置的特别大,设置大一点可以方便后续我们可以继续扩展这个链,比如说:校验的时候,有用户名校验order(1)、手机校验order(2),后续扩展的时候,如过你想在添加一种校验规则,就只能在后面添加,如果有一些场景需要添加在两者中间,我们就需要重新修改order里面的数字。

设置责任链的协调者

@Component
public class LeaveHandlerChain {
    @Autowired
    private List<TakeLeave> leaveHandlers;
    public boolean handleLeaveRequest(User user) {
        for (TakeLeave handler : leaveHandlers) {
            if (!handler.doTakeLeave(user)) {
                // 如果任何一个处理者返回false,则整个链结束
                return false;
            }
        }
        return true;
    }
}

进行测试

 @Autowired
    private LeaveHandlerChain leaveHandlerChain;

    @Test
    void test1(){
        User user = new User();
        user.setName("小杰不秃头");
        user.setReason("家里有事,需要请假");
        //user.setReason("");
        boolean isApproved  = leaveHandlerChain.handleLeaveRequest(user);
        if (isApproved) {
            System.out.println("请假已批准!");
        } else {
            System.out.println("请假被拒绝!");
        }
    }

/*
院长:已审核,提交给导员。
导员:已审核,提交给任课老师。
任课老师:已同意学生请假。
请假已批准!
*/
/*
院长:没有请假理由,拒绝请假!
请假被拒绝!
*/

总结

  • 优点:请求的发送者和接受者解耦;可以控制执行顺序;符合开闭原则单一职责原则
  • 缺点:对比较长的职责链,请求处理可能会涉及多个处理对象,性能会受到影响;增加了客户端的复杂性,可能会造成循环调用。

大家不可盲目为了使用设计模式而去使用设计模式,一定要结合具体的业务场景,选择最优的解决方法。

今天的分享就到这里,我们下个设计模式见????