责任链模式(ChainOfResponsibility)
责任链模式(ChainOfResponsibility)
ChainOfResponsibility:
责任链模式是一种行为设计模式,允许将请求沿着处理者链进行转发。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下一个处理者。
/**
* 责任链模式
*
* @author CAI
* @time 2020/10/31
*/
public class ChainOfResponsibilityPattern {
private static Server server;
private static void init() {
server = new Server();
server.register("admin", "admin");
server.register("root", "admin");
server.register("jack", "heel");
Middleware middleware = new ThrottlingMiddleware(2);
middleware.linkWith(new UserExistsMiddleware(server)).linkWith(new RoleCheckMiddleware());
server.setMiddleware(middleware);
}
public static void main(String[] args) {
init();
boolean success;
Scanner in = new Scanner(System.in);
do {
System.out.print("Enter user :");
String user = in.nextLine();
System.out.print("Input password : ");
String password = in.nextLine();
success = server.login(user, password);
} while (!success);
}
}
/**
* 中间类
*/
abstract class Middleware {
/**
* 继任者
*/
private Middleware next;
public Middleware linkWith(Middleware next) {
this.next = next;
return next;
}
/**
* 用户认证
*
* @param name 用户
* @param password 密码
* @return 认证结果
*/
public abstract Boolean check(String name, String password);
/**
* 将认证传递给继任者
*
* @param name 用户名
* @param password 密码
* @return 继任者的认证结果
*/
protected Boolean checkNext(String name, String password) {
if (name == null) {
return true;
}
return next.check(name, password);
}
}
/**
* 限制流量
*/
class ThrottlingMiddleware extends Middleware {
/**
* 请求间隔
*/
private final Integer requestPerMinute;
/**
* 请求次数
*/
private Integer request;
/**
* 当前时间
*/
private Long currentTime;
public ThrottlingMiddleware(int requestPerMinute) {
this.requestPerMinute = requestPerMinute;
this.currentTime = System.currentTimeMillis();
this.request = 0;
}
@Override
public Boolean check(String name, String password) {
if (System.currentTimeMillis() > currentTime + 60_000) {
request = 0;
currentTime = System.currentTimeMillis();
}
request++;
if (request > requestPerMinute) {
System.out.println("请求次数超过限制.");
Thread.currentThread().stop();
}
return checkNext(name, password);
}
}
/**
* 检查用户信息
*/
class UserExistsMiddleware extends Middleware {
private final Server server;
public UserExistsMiddleware(Server server) {
this.server = server;
}
@Override
public Boolean check(String user, String password) {
if (!server.hasUser(user)) {
System.out.println("该用户未注册!");
return false;
}
if (!server.isValidPassword(user, password)) {
System.out.println("密码错误!");
return false;
}
return checkNext(user, password);
}
}
class RoleCheckMiddleware extends Middleware {
@Override
public Boolean check(String user, String password) {
if ("root".equals(user) || "admin".equals(user)) {
System.out.println("Hello admin!");
return true;
}
System.out.println("Hello user!");
return checkNext(user, password);
}
}
class Server {
/**
* 用户
*/
private Map<String, String> users = new HashMap<>();
/**
* 中间件
*/
private Middleware middleware;
public void setMiddleware(Middleware middleware) {
this.middleware = middleware;
}
/**
* 登录
*
* @param user 用户
* @param password 密码
* @return 登录结果
*/
public Boolean login(String user, String password) {
if (middleware.check(user, password)) {
System.out.println("认证通过,用户登录成功!");
return true;
}
return false;
}
/**
* 注册
*
* @param user 用户
* @param password 密码
*/
public void register(String user, String password) {
users.put(user, password);
}
/**
* 判断用户是否存在
*
* @param user 用户
* @return true:存在
*/
public Boolean hasUser(String user) {
return users.containsKey(user);
}
/**
* 判断密码是否合法
*
* @param user 密码
* @return 密码合法性
*/
public Boolean isValidPassword(String user, String password) {
return users.get(user).equals(password);
}
}
- 处理者(
Handler
):声明所有具体处理者的通用接口。该接口通常包含单个方法用于处理请求,但有时还会包含一个设置链上下一个处理者的方法。 - 基础处理者(中间类):是一个可选的类,通常定义一个保存对于下一个处理者引用的成员变量。客户端通常可以使用该类定义的方法创建责任链,类中可以定义默认的处理行为如:确定存在下一个处理者在进行传递。
- 具体处理者(
ThrottlingMiddleware
等):实现请求的具体处理。每个处理者收到请求后必须决定处理请求或传递该请求;处理者通常是独立且不可变的,需要通过构造函数一次性获取所有必要的数据。 - 客户端:根据业务逻辑,动态或一次性生成责任链。请求可以发给链上的任意一个处理者,而非第一个处理者。
应用场景
- 当程序需要使用不同方式处理不同种类请求,且请求类型和顺序预先并不知道即:不知道具体的处理者,可以使用责任链模式。
- 该模式能将多个处理者连接形成一条处理链,接收到请求后,会询问每个处理者能否处理该请求;这样所有的处理者都有机会处理该请求。发送者不必显示地指定具体的接收者,也使得两者间不存在耦合。
- 当必须按顺序执行多个处理者时,可以使用该模式。
- 无论以何种顺序将处理者连接成一条链,所有请求都会严格按照顺序通过链上的处理者。
- 如果所需的处理者及其顺序必须在运行时改变,可以使用责任链模式。
- 如果在处理者类中有对引用成员变量的设定方法,就能动态地插入或移除处理者,或改变其顺序。
优缺点
- 优点:
- 能控制请求处理的顺序。
- 可以请求的发起者和执行者进行解耦,满足单一职责原则。
- 再不更改现有代码的情况下可以新增处理者,满足了开闭原则。
- 缺点:若责任链配置不当,一个请求可能到了链的末端都未被处理。
在 JAVA 中的应用
以
java
核心库为例:
javax.servlet.Filter doFilter()
java.util.logging.Logger log()