在这里插入图片描述
总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

行为型模式 -> 责任链模式,简而言之,就是将多个操作组装成一条链路进行处理。请求在链路上传递,链路上的每一个节点就是一个处理器,每个处理器都可以对请求进行处理,或者传递给链路上的下一个处理器处理。

一、责任链模式Demo1

1、AbstractCheckHandler抽象类处理器

/**
 * 抽象类处理器
 */
@Component
public abstract class AbstractCheckHandler {

    /**
     * 当前处理器持有下一个处理器的引用
     */
    @Getter
    @Setter
    private AbstractCheckHandler nextHandler;

    /**
     * 处理器执行方法
     * @param param
     * @return
     */
    public abstract Result handle(ProductVO param);

    /**
     * 处理器配置
     */
    @Setter
    @Getter
    protected ProductCheckHandlerConfig config;

    /**
     * 链路传递
     * @param param
     * @return
     */
    protected Result next(ProductVO param) {
        //下一个链路没有处理器了,直接返回
        if (Objects.isNull(nextHandler)) {
            return Result.success();
        }

        //执行下一个处理器
        return nextHandler.handle(param);
    }
}

AbstractCheckHandler表示处理器抽象类,负责抽象处理器行为。其有3个子类,分别是:

NullValueCheckHandler:空值校验处理器
PriceCheckHandler:价格校验处理
StockCheckHandler:库存校验处理器

AbstractCheckHandler 抽象类中,handle()定义了处理器的抽象方法,其子类需要重写handle()方法以实现特殊的处理器校验逻辑;

protected ProductCheckHandlerConfig config 是处理器的动态配置类,使用protected声明,每个子类处理器都持有该对象。该对象用于声明当前处理器、以及当前处理器的下一个处理器nextHandler,另外也可以配置一些特殊属性,比如说接口降级配置、超时时间配置等。

AbstractCheckHandler nextHandler 是当前处理器持有的下一个处理器的引用,当前处理器执行完毕时,便调用nextHandler执行下一处理器的handle()校验方法;

protected Result next() 是抽象类中定义的,执行下一个处理器的方法,使用protected声明,每个子类处理器都持有该对象。当子类处理器执行完毕(通过)时,调用父类的方法执行下一个处理器nextHandler。

HandlerClient 是执行处理器链路的客户端,HandlerClient.executeChain()方法负责发起整个链路调用,并接收处理器链路的返回值。

2、ProductCheckHandlerConfig处理器配置类

/**
 * 处理器配置类
 */
@AllArgsConstructor
@Data
public class ProductCheckHandlerConfig {
    /**
     * 处理器Bean名称
     */
    private String handler;
    /**
     * 下一个处理器,递归设计方式
     */
    private ProductCheckHandlerConfig next;
    /**
     * 是否降级
     */
    private Boolean down = Boolean.FALSE;
}

3、HandlerClient

/**
 * 责任链模式之客户端
 */
public class HandlerClient {

    /**
     * 执行链路
     * @param handler 处理器
     * @param param 商品参数
     * @return
     */
    public static Result executeChain(AbstractCheckHandler handler, ProductVO param) {
        //执行处理器
        Result handlerResult = handler.handle(param);
        if (!handlerResult.isSuccess()) {
            System.out.println("HandlerClient 责任链执行失败返回:" + handlerResult.toString());
            return handlerResult;
        }
        return Result.success();
    }
}

4、校验处理器

/**
 * 空值校验处理器
 */
@Component
public class NullValueCheckHandler extends AbstractCheckHandler {

    @Override
    public Result handle(ProductVO param) {
        System.out.println("空值校验 NullValueCheckHandler 开始...");

        //降级:如果配置了降级,则跳过此处理器,执行下一个处理器
        if (super.getConfig().getDown()) {
            System.out.println("空值校验 NullValueCheckHandler 已降级,跳过空值校验 NullValueCheckHandler...");
            return super.next(param);
        }

        //参数必填校验
        if (Objects.isNull(param)) {
            return Result.failure(ErrorCode.PARAM_NULL_ERROR);
        }
        //SkuId商品主键参数必填校验
        if (Objects.isNull(param.getSkuId())) {
            return Result.failure(ErrorCode.PARAM_SKU_NULL_ERROR);
        }
        //Price价格参数必填校验
        if (Objects.isNull(param.getPrice())) {
            return Result.failure(ErrorCode.PARAM_PRICE_NULL_ERROR);
        }
        //Stock库存参数必填校验
        if (Objects.isNull(param.getStock())) {
            return Result.failure(ErrorCode.PARAM_STOCK_NULL_ERROR);
        }

        System.out.println("空值校验 NullValueCheckHandler 通过...");

        //执行下一个处理器
        return super.next(param);
    }
}
/**
 * 价格校验处理器
 */
@Component
public class PriceCheckHandler extends AbstractCheckHandler {
    @Override
    public Result handle(ProductVO param) {
        System.out.println("价格校验 PriceCheckHandler 开始...");

        //非法价格校验
        boolean illegalPrice =  param.getPrice().compareTo(BigDecimal.ZERO) <= 0;
        if (illegalPrice) {
            return Result.failure(ErrorCode.PARAM_PRICE_ILLEGAL_ERROR);
        }
        //其他校验逻辑...

        System.out.println("价格校验 PriceCheckHandler 通过...");

        //执行下一个处理器
        return super.next(param);
    }
}
/**
 * 库存校验处理器
 */
@Component
public class StockCheckHandler extends AbstractCheckHandler {
    @Override
    public Result handle(ProductVO param) {
        System.out.println("库存校验 StockCheckHandler 开始...");

        //非法库存校验
        boolean illegalStock = param.getStock() < 0;
        if (illegalStock) {
            return Result.failure(ErrorCode.PARAM_STOCK_ILLEGAL_ERROR);
        }
        //其他校验逻辑..

        System.out.println("库存校验 StockCheckHandler 通过...");

        //执行下一个处理器
        return super.next(param);
    }
}

5、ProductService

@Component
public class ProductService {

    /**
     * 使用Spring注入:所有继承了AbstractCheckHandler抽象类的Spring Bean都会注入进来。Map的Key对应Bean的name,Value是name对应相应的Bean
     */
    @Resource
    private Map<String, AbstractCheckHandler> handlerMap;

    /**
     * 创建商品
     * @return
     */
    public Result createProduct(ProductVO param) {

        //参数校验,使用责任链模式
        Result paramCheckResult = this.paramCheckChain(param);
        if (!paramCheckResult.isSuccess()) {
            return paramCheckResult;
        }

        //创建商品
        return this.saveProduct(param);
    }

    /**
     * 参数校验:责任链模式
     * @param param
     * @return
     */
    private Result paramCheckChain(ProductVO param) {

        //获取处理器配置:通常配置使用统一配置中心存储,支持动态变更
        ProductCheckHandlerConfig handlerConfig = this.getHandlerConfigFile();

        //获取处理器
        AbstractCheckHandler handler = this.getHandler(handlerConfig);

        //责任链:执行处理器链路
        Result executeChainResult = HandlerClient.executeChain(handler, param);
        if (!executeChainResult.isSuccess()) {
            System.out.println("创建商品 失败...");
            return executeChainResult;
        }

        //处理器链路全部成功
        return Result.success();
    }

    /**
     * 获取处理器配置:通常配置使用统一配置中心存储,支持动态变更
     * @return
     */
    private ProductCheckHandlerConfig getHandlerConfigFile() {
        //模拟配置中心存储的配置
        String configJson = "{\"handler\":\"nullValueCheckHandler\",\"down\":false,\"next\":{\"handler\":\"priceCheckHandler\",\"next\":{\"handler\":\"stockCheckHandler\",\"next\":null}}}";
        //转成Config对象,含有下一节点的handler
        ProductCheckHandlerConfig handlerConfig = JSON.parseObject(configJson, ProductCheckHandlerConfig.class);
        return handlerConfig;
    }

    /**
     * 获取处理器
     * @param config
     * @return
     */
    private AbstractCheckHandler getHandler (ProductCheckHandlerConfig config) {
        //配置检查:没有配置处理器链路,则不执行校验逻辑
        if (Objects.isNull(config)) {
            return null;
        }
        //配置错误,则返回空
        String handler = config.getHandler();
        if (StringUtils.isBlank(handler)) {
            return null;
        }
        //配置了不存在的处理器,则返回空
        AbstractCheckHandler abstractCheckHandler = handlerMap.get(config.getHandler());
        if (Objects.isNull(abstractCheckHandler)) {
            return null;
        }

        //处理器设置配置Config
        abstractCheckHandler.setConfig(config);

        //递归设置链路处理器
        abstractCheckHandler.setNextHandler(this.getHandler(config.getNext()));

        return abstractCheckHandler;
    }


    private Result saveProduct(ProductVO param) {
        System.out.println("保存商品 成功...");
        return Result.success(param);
    }
}

configJson转换后JSON格式为
在这里插入图片描述

6、测试类ChainTests

场景1:正确输入商品参数

@SpringBootTest
public class ChainTests {

    @Resource
    ProductService productService;

    @Test
    void test1() {
        ProductVO param = ProductVO.builder()
                .skuId(123L)
                .skuName("测试商品")
                .imgPath("http://..")
                .price(new BigDecimal(1))
                .stock(1)
                .build();
        productService.createProduct(param);
    }
}

在这里插入图片描述
场景2:创建商品参数中有空值(如下skuId参数为null),链路被空值处理器截断,返回错误信息

@Test
    void contextLoads() {
        ProductVO param = ProductVO.builder()
                .skuId(null)
                .skuName("测试商品")
                .imgPath("http://..")
                .price(new BigDecimal(12))
                .stock(1)
                .build();
        productService.createProduct(param);
    }

在这里插入图片描述
场景3:创建商品价格参数异常(如下price参数),被价格处理器截断,返回错误信息

@Test
    void contextLoads() {
        ProductVO param = ProductVO.builder()
                .skuId(11L)
                .skuName("测试商品")
                .imgPath("http://..")
                .price(new BigDecimal(-101))
                .stock(1)
                .build();
        productService.createProduct(param);
    }

在这里插入图片描述
场景4:创建商品库存参数异常(如下stock参数),被库存处理器截断,返回错误信息

@Test
    void contextLoads() {
        ProductVO param = ProductVO.builder()
                .skuId(11L)
                .skuName("测试商品")
                .imgPath("http://..")
                .price(new BigDecimal(13))
                .stock(-13)
                .build();
        productService.createProduct(param);
    }

在这里插入图片描述

7、项目结构及代码

在这里插入图片描述
代码地址下载

二、责任链模式Demo2

原文–> 策略模式和责任链模式

责任链模式主要是解耦了请求与处理,客户只需将清求发送到链上即可,无需关心请求的具体内容
和处理细节,请求会自动进行传递直至有节点对象进行处理。

适用于以下应用场景 :
1)多个对象可以处理同一清求,但具体由哪个对象处理则在运行时动态决定;
2)不明确指定接收者的情况下,向多个对象中的—个提交—个请求;
3)可动态指定一组对象处理请求。
1、Member

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Member{
    private String loginName;
    private String loginPass;
    private String roleName;

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

2、Handler

public abstract class Handler {
    protected Handler next;
    public void next(Handler next){
        this.next = next;
    }
    public abstract void doHandler(Member member);
}

3、ValidateHandler

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

 }

4、LoginHandler

public class LoginHandler extends Handler {
    @Override
    public void doHandler(Member member) {
        System.out.println("登录成功,可以往下执行");
        member.setRoleName("管理员");
        next.doHandler(member);
    }
}

5、AuthHandler

public class AuthHandler extends Handler {
    @Override
    public void doHandler(Member member) {
        if (!"管理员".equals(member.getRoleName())) {
            System.out.println("您不是管理员,没有操作权限");
            return;
        }
        System.out.println("允许操作");
    }
}

6、MemberService

public class MemberService {

    public void login(String loginName, String loginPass) {
        Handler validateHandler = new ValidateHandler();
        Handler loginHandler = new LoginHandler();
        Handler authHandler = new AuthHandler();
        validateHandler.next(loginHandler);
        loginHandler.next(authHandler);
        validateHandler.doHandler(new Member(loginName, loginPass));
    }
}

7、测试

 @Test
    public void TestMemberService() {
        MemberService memberService = new MemberService();
        memberService.login("tom","666");
    }

8、测试测试
9、项目
在这里插入图片描述
代码下载

原文链接
「实战设计模式专栏」之责任链模式

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐