责任链模式(学习笔记2021.09.18)

责任链模式(学习笔记2021.09.18)

前言:

为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

**意图:**避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

**主要解决:**职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

**何时使用:**在处理消息的时候以过滤很多道。

**如何解决:**拦截的类都实现统一接口。

**关键代码:**Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。

应用实例: JAVA WEB 中 Apache Tomcat 对 Encoding 的处理, jsp servlet 的 Filter。

优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。

缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。

使用场景: 当你想要一个以上的对象有机会能够处理某个请求的时候, 就使用责任链模式。

前提条件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UGgXVAPK-1631964770102)(https://z3.ax1x.com/2021/09/18/4lKWex.md.png)]

从上面的条件可以看出, 我们需要写一个程序, 接收人工智能程序分类好的所有邮件, 将所有邮件一层层往下处理。

如果使用责任链

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VHOh6Z3d-1631964770104)(https://z3.ax1x.com/2021/09/18/4lMWcj.md.png)]

下面实现责任链模式

  • Handler: 抽象处理者。定义了一个处理请求的方法。所有的处理者都必须实现该抽象类。
  • ConcreteHandler: 具体处理者。处理它所负责的请求,同时也可以访问它的后继者。如果它能够处理该请求则处理,否则将请求传递到它的后继者。
  • Client: 客户类。

1.0 创建邮件实体

/**
 * @Author: ZhiHao
 * @Date: 2021/9/18 17:05
 * @Description: 邮件
 * @Versions 1.0
 **/
@Data
@AllArgsConstructor
public class Mail {
    // 邮件的类型
    private String mailType;
    // 邮件内容
    private String mailContent;
}

2.0 创建处理责任链抽象 (抽象处理者)

/**
 * @Author: ZhiHao
 * @Date: 2021/9/18 17:12
 * @Description: 邮件处理程序抽象
 * @Versions 1.0
 **/
public abstract class MailHandler implements Ordered {
    // 下一位处理的人
    protected MailHandler successor;
    // 设置下一位处理人
    public void setNextSuccessor(MailHandler successor) {
        this.successor = successor;
    }
    // 处理请求
    public void handlerRequest(List<Mail> mailList) {
        this.doHandler(mailList);
    }
    // 真正处理请求, 让子类处理程序去做
    protected abstract void doHandler(List<Mail> mailList);
}

3.0 具体处理者

/**
 * @Author: ZhiHao
 * @Date: 2021/9/18 17:29
 * @Description: 辣鸡邮件处理程序
 * @Versions 1.0
 **/
public class SpamHandler extends MailHandler {

    @Override
    protected void doHandler(List<Mail> mailList) {
        List<Mail> collect = mailList.stream().filter((obj) -> "Spam".equals(obj.getMailType())).collect(Collectors.toList());
        System.out.println("SpamHandler, 处理了:" + collect);
        // 传递处理后的资源给下一个处理人
        Optional.ofNullable(this.successor).ifPresent((successor) -> successor.handlerRequest(mailList));
    }

    @Override
    public int getOrder() {
        return 1;
    }
}
//-----------------------------------------------------------------------
public class FanHandler extends MailHandler {

    @Override
    protected void doHandler(List<Mail> mailList) {
        List<Mail> collect = mailList.stream().filter((obj) -> "Fan".equals(obj.getMailType())).collect(Collectors.toList());
        System.out.println("FanHandler, 处理了:"+collect);
        // 传递处理后的资源给下一个处理人
        Optional.ofNullable(this.successor).ifPresent((successor)->successor.handlerRequest(collect));
    }

    @Override
    public int getOrder() {
        return 2;
    }
}
//-----------------------------------------------------------------------
public class NewLocHandler extends MailHandler {

    @Override
    protected void doHandler(List<Mail> mailList) {
        List<Mail> collect = mailList.stream().filter((obj) -> "NewLoc".equals(obj.getMailType())).collect(Collectors.toList());
        System.out.println("NewLocHandler, 处理了:"+collect);
        // 传递处理后的资源给下一个处理人
        Optional.ofNullable(this.successor).ifPresent((successor)->successor.handlerRequest(collect));
    }

    @Override
    public int getOrder() {
        return 3;
    }
}

4.0 测试

@Test
    public void applicationTest() throws Exception {
        // 创建邮件集合
        List<Mail> mailList = Arrays.asList(new Mail("Spam", "我是个Spam辣鸡邮件"),
                new Mail("NewLoc", "我是个NewLoc邮件"),
                new Mail("Fan", "我是个Fan邮件"));
        MailHandler mailHandler = this.initMailHandler();
        mailHandler.handlerRequest(mailList);
    }

    private MailHandler initMailHandler() {
        // 设置1号处理人
        MailHandler one = new SpamHandler();
        // 1号里面设置2号处理人
        FanHandler two = new FanHandler();
        one.setNextSuccessor(two);
        // 2号里面设置3号处理人
        NewLocHandler three = new NewLocHandler();
        two.setNextSuccessor(three);
        return one;
    }
//------------------
SpamHandler, 处理了:[Mail(mailType=Spam, mailContent=我是个Spam辣鸡邮件)]
FanHandler, 处理了:[]
NewLocHandler, 处理了:[]

要获取责任链最终结果的情况下, 将保存的结果数据结构对象, 当方法参数传递进去, 最终处理完责任链, 方法对象参数也修改完毕了, 或者在责任链每个处理者内部往下一个处理者设置属性。

责任链模式通过建立一条链来组织请求的处理者,请求将沿着链进行传递,请求发送者无须知道请求在何时、何处以及如何被处理,实现了请求发送者与处理者的解耦

  • 责任链模式和状态模式:责任链模式当中各个对象并不指定下一个处理的对象者是谁,只有在客户端来设定链条中的顺序以及元素,直到被某个元素处理,或者整个链条结束,状态模式是让每个状态模式知道自己下一个处理的对象是谁,也就是说在编译时就设定好了,这个是他俩最大的区别。

扩展: 另一种类似责任链

循环方式责任

这种方式是外部循环, 将请求转给下一个处理者

public interface OrderScreeningBase extends Ordered {
    boolean support(Object... objs);
    void orderScreening(OrderScreeningDto orderScreeningDto);
    OrderScreeningEnum getAddressLabelEnum();
}
------------------------------------------------------------------------------------------------
public enum OrderScreeningEnum {

    SIMILAR_ADDRESS(1, "相近地址", AuthSpringUtil.getBean(SimilarAddressScreening.class)),
    SIMILAR_CLIENT_ADDRESS(2, "相近客户地址", AuthSpringUtil.getBean(SimilarClientAddressScreening.class)),
    SIMILAR_LOGISTICS_ADDRESS(3, "相近物流地址", AuthSpringUtil.getBean(SimilarLogisticsAddressScreening.class)),
    ;
    private Integer code;
    private String remark;
    private OrderScreeningBase supplier;
    private static List<OrderScreeningBase> orderScreeningBaseList;

    static {
        orderScreeningBaseList = Arrays.stream(OrderScreeningEnum.values())
                .map(addressLabelEnum -> addressLabelEnum.supplier)
                .sorted(Comparator.comparing(orderScreeningBase -> orderScreeningBase.getOrder()))
                .collect(Collectors.toList());
    }

    OrderScreeningEnum(Integer code, String remark, OrderScreeningBase supplier) {
        this.code = code;
        this.remark = remark;
        this.supplier = supplier;
    }

    public static List<OrderScreeningBase> getOrderScreeningBaseList() {
        return orderScreeningBaseList;
    }
}
---------------------------------------使用方式-----------------------------------------------
for (OrderScreeningBase screeningBase : OrderScreeningEnum.getOrderScreeningBaseList()) {
                if (screeningBase.support(orderScreeningDto.getHitQuantity())) {
                    // do 相同订单筛选
                    screeningBase.orderScreening(orderScreeningDto);
                }
            }    

1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懵懵懂懂程序员

如果节省了你的时间, 请鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值