责任链模式(Chain of Responsibility Pattern)
定义
将请求的发送和接收解耦,让多个对象都有机会依次处理这个请求,形成一个链条。
责任链模式是将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。
当一个请求从链式的首端发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。
属于行为型模式。
适用场景:
1.多个对象可以处理同一个请求,具体由哪个对象处理则在运行时动态决定;
2.在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
3.可动态指定一组对象处理请求。
标准示例
Handler 是一个抽象的处理器,下一个节点在handler中维护;
ConcreteHandlerA、ConcreteHandlerB 是两个具体的处理者。它们只处理自己职责范围内的事情,与自己无关的,抛给下一个节点来处理;
每个具体的处理者,在链条中,依次传递下去,直到找到负责该职责的处理者。
具体代码如下:
Handler
public abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler){
this.nextHandler = nextHandler;
}
public abstract void handlerRequest(String request);
}
ConcreteHandlerA
public class ConcreteHandlerA extends Handler{
public void handlerRequest(String request) {
if("A".equals(request)){
System.out.println(this.getClass().getSimpleName()+" 收到请求参数:"+request);
return ;
}
if(this.nextHandler!=null){
this.nextHandler.handlerRequest(request);
}
}
}
ConcreteHandlerB
public class ConcreteHandlerB extends Handler{
public void handlerRequest(String request) {
if("B".equals(request)){
System.out.println(this.getClass().getSimpleName()+" 收到请求参数:"+request);
return ;
}
if(this.nextHandler!=null){
this.nextHandler.handlerRequest(request);
}
}
}
Client
public class Client {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setNextHandler(handlerB);
handlerA.handlerRequest("B");
}
}
client 执行结果:
ConcreteHandlerB 收到请求参数:B
再举个实际场景的例子。
我们在登录系统的时候,会有多种途径,比如账号密码,比如手机号验证码,比如微信三方授权登录。
我们就用责任链模式来实现这个业务逻辑。
我们使用BaseLoginHandler作为抽象的处理器。
AccountLoginHandler、PhoneLoginHandler、WxLoginHandler 作为具体的处理者。
代码如下:
BaseLoginHandler
@Data
public abstract class BaseLoginHandler {
protected BaseLoginHandler nextHandler;
public abstract void requestHandler(LoginRequestDTO request);
}
AccountLoginHandler
public class AccountLoginHandler extends BaseLoginHandler {
public void requestHandler(LoginRequestDTO request) {
if(!StringUtils.isAnyBlank(request.getAccount(),request.getPassword())){
System.out.println("进入账号密码登录逻辑");
return;
}
if(this.nextHandler!=null){
this.nextHandler.requestHandler(request);
}
}
}
PhoneLoginHandler
public class PhoneLoginHandler extends BaseLoginHandler{
public void requestHandler(LoginRequestDTO request) {
if(!StringUtils.isAnyBlank(request.getPhoneNo(),request.getVerifyCode())){
System.out.println("进入手机号验证码登录逻辑");
return ;
}
if(this.nextHandler!=null){
this.nextHandler.requestHandler(request);
}
}
}
WxLoginHandler
public class WxLoginHandler extends BaseLoginHandler{
public void requestHandler(LoginRequestDTO request) {
if(StringUtils.isNotBlank(request.getWxOpenId())){
System.out.println("进入微信授权登录逻辑");
return ;
}
if(this.nextHandler!=null){
this.nextHandler.requestHandler(request);
}
}
}
LoginRequestDTO
请求参数
@Data
public class LoginRequestDTO {
private String account;
private String password;
private String phoneNo;
private String verifyCode;
private String wxOpenId;
}
ClientTest
public class ClientTest {
public static void main(String[] args) {
//请求参数中只含有wxOpenid
LoginRequestDTO requestDTO = new LoginRequestDTO();
requestDTO.setWxOpenId("afjqweriqwjn1231324nzkfjasldfj");
AccountLoginHandler accountHandler = new AccountLoginHandler();
PhoneLoginHandler phoneHandler = new PhoneLoginHandler();
WxLoginHandler wxHandler = new WxLoginHandler();
//设置责任链顺序:account -> phone -> wx
accountHandler.setNextHandler(phoneHandler);
phoneHandler.setNextHandler(wxHandler);
//执行责任链
accountHandler.requestHandler(requestDTO);
}
}
执行结果:
进入微信授权登录逻辑
小提示: 代码中用到的 StringUtils 是 Apache common 工具包中的,可在pom.xml中引入:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
以上就是责任链模式全部内容,感谢阅读。