责任链模式(学习笔记2021.09.18)
前言:
为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
**意图:**避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
**主要解决:**职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
**何时使用:**在处理消息的时候以过滤很多道。
**如何解决:**拦截的类都实现统一接口。
**关键代码:**Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
应用实例: JAVA WEB 中 Apache Tomcat 对 Encoding 的处理, jsp servlet 的 Filter。
优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。
使用场景: 当你想要一个以上的对象有机会能够处理某个请求的时候, 就使用责任链模式。
前提条件:
从上面的条件可以看出, 我们需要写一个程序, 接收人工智能程序分类好的所有邮件, 将所有邮件一层层往下处理。
如果使用责任链
下面实现责任链模式
- 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