Java中常用的设计模式之责任链模式详解

 更新时间:2022年02月27日 11:56:38   作者:Asurplus、  
这篇文章主要为大家详细介绍了Java中常用的设计模式之责任链模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

优点

1.降低耦合度。它将请求的发送者和接收者解耦。

2.简化了对象。使得对象不需要知道链的结构。

3.增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。

4、增加新的请求处理类很方便。

缺点

1.不能保证请求一定被接收。

2.系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。

3.可能不容易观察运行时的特征,有碍于除错。

使用场景

1.有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。

2.在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

3.可动态指定一组对象处理请求。

一、实现方式

假设一个场景,学校里,校长的职能大于老师,老师的职能大于学生,基于这样的链路关系,学生处理不了的事情上报给老师,老师处理不了的事情上报给校长。

1、处理抽象类

package com.asurplus.common.handle.style1;
/**
 * 处理抽象类
 */
public abstract class Handler {
    /**
     * 下一个处理类
     */
    protected Handler handler;
    public void setHandler(Handler handler) {
        this.handler = handler;
    }
    public Handler getHandler() {
        return handler;
    }

    /**
     * 处理事件
     *
     * @param request
     */
    public abstract void handlerRequest(String request);
}

2、学生处理类

package com.asurplus.common.handle.style1;
import lombok.extern.slf4j.Slf4j;
/**
 * 学生处理类
 */
@Slf4j
public class StudentHandler extends Handler {
    @Override
    public void handlerRequest(String request) {
        if ("打扫卫生".equals(request)) {
            log.info("学生处理中");
        } else {
            this.handler.handlerRequest(request);
        }
    }
}

学生能处理“打扫卫生”这件事,如果是其他事件,交给他的下一个元素

3、老师处理类

package com.asurplus.common.handle.style1;
import lombok.extern.slf4j.Slf4j;
/**
 * 老师处理类
 */
@Slf4j
public class TeacherHandler extends Handler {
    @Override
    public void handlerRequest(String request) {
        if ("批改试卷".equals(request)) {
            log.info("老师处理中");
        } else {
            this.handler.handlerRequest(request);
        }
    }
}

老师能处理“批改试卷”这件事,如果是其他事件,交给他的下一个元素

4、校长处理类

package com.asurplus.common.handle.style1;
import lombok.extern.slf4j.Slf4j;
/**
 * 校长处理类
 */
@Slf4j
public class HeadHandler extends Handler {
    @Override
    public void handlerRequest(String request) {
        if ("学籍问题".equals(request)) {
            log.info("校长处理中");
        } else {
            log.error("无法处理该事件");
        }
    }
}

校长能处理“学籍问题”这件事,如果是其他事件,由于我们的责任链只有三级,都处理不了,只能打印日志了

5、测试

package com.asurplus.common.handle.style1;
/**
 * 责任链模式
 */
public class TestMain {
    public static void main(String[] args) {
        // 学生处理器
        StudentHandler studentHandler = new StudentHandler();
        // 老师处理器
        TeacherHandler teacherHandler = new TeacherHandler();
        // 校长处理器
        HeadHandler headHandler = new HeadHandler();
        // 老师的上一级是校长
        teacherHandler.setHandler(headHandler);
        // 学生的上一级是老师
        studentHandler.setHandler(teacherHandler);
        // 处理 批改试卷 这件事
        studentHandler.handlerRequest("批改试卷");
    }
}

输出结果

在这里插入图片描述

可以看出,“批改试卷”这件事,被老师处理了。

二、实现方式

假设一个场景,在我们的电商系统中,当创建一个订单的时候,我们需要去校验很多的数据,我们需要去判断该商品存不存在,库存还有没有,价格对不对,等等校验。

1、订单信息类

package com.asurplus.common.handle.style2;
import lombok.Builder;
import lombok.Data;
/**
 * 订单信息
 */
@Data
@Builder
public class Order {
    // 库存
    private int stock;
    // 单价
    private int price;
}

2、订单校验接口

package com.asurplus.common.handle.style2;
/**
 * 校验器接口
 *
 * @param <T>
 */
public interface OrderFilter<T> {
    /**
     * 业务逻辑
     *
     * @param t
     * @return
     */
    boolean execute(T t);
}

3、库存校验器

package com.asurplus.common.handle.style2;
import lombok.extern.slf4j.Slf4j;
/**
 * 库存校验器
 */
@Slf4j
public class OrderStockFilter implements OrderFilter<Order> {
    @Override
    public boolean execute(Order order) {
        if (0 >= order.getStock()) {
            log.error("库存不足");
            return false;
        }
        return true;
    }
}

4、价格校验器

package com.asurplus.common.handle.style2;
import lombok.extern.slf4j.Slf4j;
/**
 * 价格校验器
 */
@Slf4j
public class OrderPriceFilter implements OrderFilter<Order> {
    @Override
    public boolean execute(Order order) {
        if (0 > order.getPrice()) {
            log.error("价格错误");
            return false;
        }
        return true;
    }
}

5、测试

package com.asurplus.common.handle.style2;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;
/**
 * 责任链模式
 */
@Slf4j
public class TestMain {
    public static void main(String[] args) {
        // 建造者模式创建一个订单
        Order order = Order.builder().stock(0).price(0).build();
        // 库存校验器
        OrderStockFilter orderQuantityFilter = new OrderStockFilter();
        // 价格校验器
        OrderPriceFilter orderPriceFilter = new OrderPriceFilter();
        // 组装成一个list
        List<OrderFilter<Order>> orderFilters = Arrays.asList(orderQuantityFilter, orderPriceFilter);
        boolean res = false;
        // 循环校验
        for (OrderFilter<Order> item : orderFilters) {
            res = item.execute(order);
            // 其中任何一项不通过就停止校验
            if (!res) {
                break;
            }
        }
        if (!res) {
            log.error("下单失败");
        }
    }
}

在这里插入图片描述

被我们的“库存校验器”校验不通过,导致下单失败。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!    

相关文章

  • Java线程池大小的设置方法实例

    Java线程池大小的设置方法实例

    线程池的设置是有方法的,不是凭借简单的估算来决定的,这篇文章主要给大家介绍了关于Java线程池大小的设置方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-08-08
  • Spring Security使用单点登录的权限功能

    Spring Security使用单点登录的权限功能

    本文主要介绍了Spring Security使用单点登录的权限功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • java中的动态代理与责任链模式详解

    java中的动态代理与责任链模式详解

    这篇文章主要介绍了java中的动态代理与责任链模式详解,动态代理提供了一种灵活且非侵入式的方式,可以对对象的行为进行定制和扩展,它在代码重用、解耦和业务逻辑分离、性能优化以及系统架构中起到了重要的作用,需要的朋友可以参考下
    2023-08-08
  • Spring Boot环境属性占位符解析及类型转换详解

    Spring Boot环境属性占位符解析及类型转换详解

    这篇文章主要给大家介绍了关于Spring Boot环境属性占位符解析及类型转换的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • java基于正则表达式实现时间日期的常用判断操作实例

    java基于正则表达式实现时间日期的常用判断操作实例

    这篇文章主要介绍了java基于正则表达式实现时间日期的常用判断操作,简单说明了正则表达式常用元字符含义并结合实例形式分析了java基于正则表达式针对常用日期时间格式的判断操作技巧,需要的朋友可以参考下
    2017-10-10
  • 改善Java代码之慎用java动态编译

    改善Java代码之慎用java动态编译

    这篇文章主要介绍了改善Java代码之慎用java动态编译,需要的朋友可以参考下
    2021-04-04
  • Spring 容器初始化 register 与 refresh方法

    Spring 容器初始化 register 与 refresh方法

    这篇文章主要介绍了Spring 容器初始化 register 与 refresh方法,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-07-07
  • java环境变量配置超详细图文教程

    java环境变量配置超详细图文教程

    在我们学习Java语言的时候,要在命令提示符里运用Java和Javac,用到这两个命令的时候就要配置Java环节变量才可以,这篇文章主要给大家介绍了关于java环境变量配置的相关资料,需要的朋友可以参考下
    2023-10-10
  • JAVA设计模式之访问者模式详解

    JAVA设计模式之访问者模式详解

    这篇文章主要介绍了JAVA设计模式之访问者模式详解,访问者模式是对象的行为模式,访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,需要的朋友可以参考下
    2015-04-04
  • Spring Boot使用profile如何配置不同环境的配置文件

    Spring Boot使用profile如何配置不同环境的配置文件

    ,springboot支持通过不同的profile来配置不同环境的配置,下面就大致介绍一下yml配置文件跟properties配置文件怎么使用profile配置不同环境的配置文件
    2018-01-01

最新评论