一、责任链模式
1、定义
责任链模式(Chain of Responsibility Pattern)
,是指将链中每一个节点都看作一个对象,每个节点处理的请求均不同,且内部自动维护下一个节点对象。当一个请求从链式的首端发出时,会沿着责任链预设的路径依次传递到每一个节点对象,直到被链中的某个对象处理为止,属于行为型设计模式。
责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与处理。
2、结构
(1)模式的结构
主要角色如下:
- 抽象处理者(Handler):定义一个请求处理的方法,并维护一个下一处理节点的 Handler对象的引用。
- 具体处理者(ConcreteHandler):对请求进行处理,如果不感兴趣,则进行转发到它的下一个节点。
3、优缺点
优点:
- 将请求与处理解耦。
- 请求处理者只需关注自己感兴趣的请求进行处理即可,对于不感兴趣的请求,直接转发给下一个节点处理。
- 链路结构灵活,可以通过盖帘链结构动态地新增或删减责任。
- 易扩展,符合开闭原则
缺点:
- 责任链太长或者处理时间太长,会影响整体性能。
- 如果节点对象存在循环引用,则会造成死循环,导致系统崩溃。
4、使用场景
- 多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交请求。
- 可动态指定一组对象处理请求。
5、在框架源码中使用
- Java中的 Filter类。
- Spring Security或者Shiro都用到责任链模式。
二、模式的通用实现
代码如下:
public class ChainOfResponsibilityPattern {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setNextHandler(handlerB);
handlerA.doHandle("A");
System.out.println("----------");
handlerA.doHandle("B");
System.out.println("----------");
handlerA.doHandle("C");
}
}
//抽象处理者
abstract class Handler{
// 下一个节点对象引用
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void doHandle(String request);
}
// 具体处理者
class ConcreteHandlerA extends Handler{
@Override
public void doHandle(String request) {
if("A".equals(request)){
System.out.println("ConcreteHandlerA 处理请求");
return;
}
if(this.nextHandler != null){
this.nextHandler.doHandle(request);
}
}
}
class ConcreteHandlerB extends Handler{
@Override
public void doHandle(String request) {
if("B".equals(request)){
System.out.println("ConcreteHandlerB 处理请求");
return;
}
if(this.nextHandler != null){
this.nextHandler.doHandle(request);
}
}
}
三、模式的应用实例
已授权登录校验为例。
@Data
public class User {
private String username;
private String pazzWord;
private String roleName;
}
示例一
责任链模式编写:
(1)抽象处理类
public abstract class WebHandler {
protected WebHandler chain;
public void next(WebHandler Handler){
this.chain = Handler;
}
public abstract void doHandle(User user);
}
(2)具体处理类
public class ValidateWebHandler extends WebHandler{
@Override
public void doHandle(User user) {
if(user == null){
System.out.println("用户为空");
return;
}
if(StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPazzWord())){
System.out.println("用户名或者密码为空");
return;
}
System.out.println("用户信息校验成功。向下一个执行");
this.chain.doHandle(user);
}
}
public class LoginWebHandler extends WebHandler{
@Override
public void doHandle(User user) {
System.out.println("查询数据库,用户登录成功。");
user.setRoleName("admin");
System.out.println("查询用户角色,向下一个执行");
this.chain.doHandle(user);
}
}
public class AuthWebHandler extends WebHandler{
@Override
public void doHandle(User user) {
if("admin".equals(user.getRoleName())){
System.out.println("管理员上线,允许进行全部操作");
return;
}else{
System.out.println("普通用户上线,正常权限进行操作");
}
}
}
(3)测试
public static void main(String[] args) {
WebHandler validateWebHandler = new ValidateWebHandler();
WebHandler loginWebHandler = new LoginWebHandler();
WebHandler authWebHandler = new AuthWebHandler();
validateWebHandler.next(loginWebHandler);
loginWebHandler.next(authWebHandler);
User user = new User();
user.setUsername("赵云");
user.setPazzWord("123456");
validateWebHandler.doHandle(user);
}
示例二
针对复杂结构的责任链组装。我们可以结合建造者模式一起使用。
(1)抽象处理类
public abstract class WebHandler2<T> {
protected WebHandler2 chain;
private void next(WebHandler2 Handler) {
this.chain = Handler;
}
public abstract void doHandle(User user);
public static class Builder<T> {
private WebHandler2<T> head;
private WebHandler2<T> tail;
public Builder<T> addWebHandler(WebHandler2<T> webHandler2) {
if (this.head == null) {
this.head = this.tail = webHandler2;
return this;
}
this.tail.next(webHandler2);
this.tail = webHandler2;
return this;
}
public WebHandler2<T> build() {
return this.head;
}
}
}
(2)具体处理类
public class ValidateWebHandler extends WebHandler2{
@Override
public void doHandle(User user) {
if(user == null){
System.out.println("用户为空");
return;
}
if(StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPazzWord())){
System.out.println("用户名或者密码为空");
return;
}
System.out.println("用户信息校验成功。向下一个执行");
this.chain.doHandle(user);
}
}
public class LoginWebHandler extends WebHandler2{
@Override
public void doHandle(User user) {
System.out.println("查询数据库,用户登录成功。");
user.setRoleName("admin");
System.out.println("查询用户角色,向下一个执行");
this.chain.doHandle(user);
}
}
public class AuthWebHandler extends WebHandler2{
@Override
public void doHandle(User user) {
if("admin".equals(user.getRoleName())){
System.out.println("管理员上线,允许进行全部操作");
return;
}else{
System.out.println("普通用户上线,正常权限进行操作");
}
}
}
(3)测试
public static void main(String[] args) {
WebHandler2.Builder<Object> webHandler2 = new WebHandler2.Builder<>();
webHandler2.addWebHandler(new ValidateWebHandler2())
.addWebHandler(new LoginWebHandler2())
.addWebHandler(new AuthWebHandler2());
User user = new User();
user.setUsername("赵子龙");
user.setPazzWord("123456");
webHandler2.build().doHandle(user);
}
– 求知若饥,虚心若愚。