责任链模式概念
责任链模式为请求创建了一个接收者对象的链,每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,沿着这条链传递请求,直到有对象处理它为止。
责任链模式解决的事
客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
看可以用到的场景:
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
简单实现一下:
package com.example.designmode.crp;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* <h3>design-mode</h3>
* <p>定义一个请求</p>
*
* @author : ZhangYuJie
* @date : 2022-06-19 19:09
**/
@Data
@AllArgsConstructor
public class Request {
private String name;
private int days;
}
package com.example.designmode.crp;
import lombok.Data;
/**
* <h3>design-mode</h3>
* <p>定义一个返回结果</p>
*
* @author : ZhangYuJie
* @date : 2022-06-19 19:10
**/
@Data
public class Result {
private boolean agree;
public Result(boolean agree) {
this.agree = agree;
}
}
package com.example.designmode.crp;
/**
* <h3>design-mode</h3>
* <p></p>
*
* @author : ZhangYuJie
* @date : 2022-06-19 19:10
**/
public interface Handler {
/**
* 每个处理器持有链,能取到链上的请求或者传递请求
* @param chain
* @return
*/
Result deal(Chain chain);
interface Chain {
/**
* 获取请求
* @return
*/
Request request();
/**
* 传递请求
* @param request
* @return
*/
Result proceed(Request request);
}
}
package com.example.designmode.crp;
import java.util.LinkedList;
import java.util.Queue;
/**
* <h3>design-mode</h3>
* <p>定义一个处理接口的链</p>
*
* @author : ZhangYuJie
* @date : 2022-06-19 19:11
**/
public class HandlerChain implements Handler.Chain {
/**
* 持有链要处理的请求
*/
private final Request request;
/**
* 持有链上所有的处理器
*/
private Queue<Handler> handlers;
public HandlerChain(Request request) {
this.request = request;
}
/**
* <h3>design-mode</h3>
* <p>添加处理器</p>
* @param handler
* @return
*/
public HandlerChain addHandler(Handler handler) {
if (handlers == null) {
handlers = new LinkedList<>();
}
handlers.add(handler);
return this;
}
/**
* 实现接口的方法- 获取请求
* @return
*/
public Request request() {
return request;
}
/**
* 实现接口的方法- 处理请求
* @param request
* @return
*/
public Result proceed(Request request) {
// 取队首的处理器开始请求。如果队首的处理器处理了,直接返回结果
// 如果队首的处理器选择传递请求,又会进这个proceed方法。取新的队首处理
// 为什么是传递而不是直接遍历队列,如果result = null,继续;result != null,返回呢? 因为传递的方式,可以对request再次处理。A处理器可以做简单处理,再传递给B。
Handler handler = handlers.poll();
assert handler != null;
return handler.deal(this);
}
}
定义三个处理者
package com.example.designmode.crp;
/**
* <h3>design-mode</h3>
* <p></p>
*
* @author : ZhangYuJie
* @date : 2022-06-19 19:11
**/
public class AHandler implements Handler {
public Result deal(Chain chain) {
Request request = chain.request();
// 只处理小于等于1的请求,大于1的请求被传递了
if (request.getDays() > 1) {
// 这里可以对request做部分处理,再传递
return chain.proceed(request);
}
System.out.println("A处理了");
return new Result(true);
}
}
package com.example.designmode.crp;
public class BHandler implements Handler {
public Result deal(Chain chain) {
Request request = chain.request();
// 只处理小于等于2的请求,大于2的请求被传递了
if (request.getDays() > 2) {
return chain.proceed(request);
}
System.out.println("B处理了");
return new Result(true);
}
}
package com.example.designmode.crp;
public class CHandler implements Handler {
public Result deal(Chain chain) {
Request request = chain.request();
// 只处理小于等于3的请求,大于3的请求被传递了
if (request.getDays() > 3) {
return chain.proceed(request);
}
System.out.println("C处理了");
return new Result(true);
}
}
测试
package com.example.designmode.crp;
/**
* <h3>design-mode</h3>
* <p></p>
*
* @author : ZhangYuJie
* @date : 2022-06-19 19:13
**/
public class Test {
public static void main(String[] args) {
// new 一个链,往链上添加处理器
Request request1 = new Request("ZYJ", 3);
HandlerChain chains = new HandlerChain(request1)
.addHandler(new AHandler())
.addHandler(new BHandler())
.addHandler(new CHandler());
Result result1 = chains.proceed(request1);
System.out.println("结果:" + result1.isAgree());
}
}
输出结果
传入3:
返回:
C处理了
结果:true
传入2:
返回:
B处理了
结果:true
传入1:
返回:
A处理了
结果:true
通过这个demo发现这种模式可以在一定的场景下代替掉if else