设计模式-责任链模式
定义
责任链模式(Chain of Responsibility Pattern)是将链中的每一个节点当做一个对象,每个节点处理的请求不同,且内部自动维护一个下一个节点的对象。当一个请求从链的首端出发时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。
属于行为模式
适用场景
- 多个对象可以处理一个请求,但具体由哪个对象处理由动态决定。
- 在不指定明确接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态地指定一组对象处理请求
代码示例
普通写法
拿处理请求举例:
- 定义 Handler 抽象类,提供设置下一 handler 方法
package com.black.design.pattern.responsibilitychain.general;
// 抽象类
public abstract class Handler {
protected Handler sucessor;
public void setNextHandler(Handler sucessor) {
this.sucessor = sucessor;
}
public abstract void handleRequest(String request) ;
}
- 定义 ConcreHandlerA 类,只能处理 requestA 请求,其他请求则让下一个处理类处理
package com.black.design.pattern.responsibilitychain.general;
public class ConcreHandlerA extends Handler {
@Override
public void handleRequest(String request) {
if("requestA".equals(request)) {
System.out.println(this.getClass().getSimpleName() + "handle with request [" +request +"]");
return;
}
if (this.sucessor != null) {
sucessor.handleRequest(request);
}
}
}
- 定义 ConcreHandlerB 类,只能处理 requestB 请求,其他请求则让下一个处理类处理
package com.black.design.pattern.responsibilitychain.general;
public class ConcreHandlerB extends Handler {
@Override
public void handleRequest(String request) {
if("requestB".equals(request)) {
System.out.println(this.getClass().getSimpleName() + "handle with request [" +request +"]");
return;
}
if (this.sucessor != null) {
sucessor.handleRequest(request);
}
}
}
- 测试
package com.black.design.pattern.responsibilitychain.general;
//测试类
public class HandlerTest {
public static void main(String[] args) {
// 实例化 handlerA 处理类
Handler handlerA = new ConcreHandlerA();
// 实例化 handlerB 处理类
Handler handlerB = new ConcreHandlerB();
// handlerA 下一节点是 handlerB 处理类
handlerA.setNextHandler(handlerB);
// 定义 3 个请求
String[] reqs = {"requestA","requestB","requestC"};
// 循环处理
for (int i = 0; i < reqs.length; i++) {
handlerA.handleRequest(reqs[i]);
}
}
}
结果:
ConcreHandlerAhandle with request [requestA]
ConcreHandlerBhandle with request [requestB]
登录场景
基本流程:
- 验证用户名和密码是否为空
- 登录验证,成功后获取用户权限
- 验证权限
代码如下:
- 登录接口
package com.black.design.pattern.responsibilitychain.auth;
// 登录接口类
public interface LoginService {
// 根据用户名和密码登录
public void login(String userName, String password);
}
package com.black.design.pattern.responsibilitychain.auth;
// 登录接口实现类
public class LoginServiceImpl implements LoginService {
public void login(String userName, String password) {
// 校验用户名密码是否为null
Handler vHandler = new ValidatorHandler();
// 登录
Handler loginHandler = new LoginHandler();
// 校验是否有权限
Handler authHandler = new AuthHandler();
//执行
vHandler.next(loginHandler);
loginHandler.next(authHandler);
vHandler.doHandle(new UserInfo(userName, password));
}
}
package com.black.design.pattern.responsibilitychain.auth;
// 用户信息
public class UserInfo {
// 用户名
private String userName;
// 密码
private String password;
// 角色
private String role;
public UserInfo(String userName, String password) {
this.userName = userName;
this.password = password;
}
public String getUserName() {
return userName;
}
public String getPassword() {
return password;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
- 创建抽象处理类
package com.black.design.pattern.responsibilitychain.auth;
// 处理类
public abstract class Handler {
// 下一处理类
protected Handler nextHandler;
// 处理方法
protected abstract void doHandle(UserInfo userInfo) ;
// 设置下一处理
public void next(Handler h) {
this.nextHandler = h;
}
}
- 登录参数校验处理类
package com.black.design.pattern.responsibilitychain.auth;
// 登录参数验证处理类
public class ValidatorHandler extends Handler {
@Override
protected void doHandle(UserInfo userInfo) {
// 校验参数
if(userInfo.getUserName() == null ||
userInfo.getPassword() == null) {
System.out.println("用户名或密码为空,不允许登录!");
return;
}
System.out.println("用户名和密码不为空,继续");
nextHandler.doHandle(userInfo);
}
}
- 登录处理类
package com.black.design.pattern.responsibilitychain.auth;
// 登录处理类
public class LoginHandler extends Handler {
@Override
protected void doHandle(UserInfo userInfo) {
System.out.println("登录成功!");
// 登录成功设置用户权限
//userInfo.setRole("业务员");
userInfo.setRole("管理员");
nextHandler.doHandle(userInfo);
}
}
- 权限验证处理类
package com.black.design.pattern.responsibilitychain.auth;
// 权限验证处理类
public class AuthHandler extends Handler {
@Override
protected void doHandle(UserInfo userInfo) {
if(!"管理员".equals(userInfo.getRole())) {
System.out.println("您不是管理员,没有操作权限");
return;
}
System.out.println("允许操作");
}
}
测试类
package com.black.design.pattern.responsibilitychain.auth;
// 测试类
public class AuthTest {
public static void main(String[] args) {
LoginService loginService = new LoginServiceImpl();
loginService.login("black", "abc");
}
}
测试结果:
用户名和密码不为空,继续
登录成功!
允许操作
优化版:
主要优化点: 增加 Handler Builder 类,用于构建 Handler 处理链。只需要调整 Handler 类和 LoginServiceImpl 类即可。
package com.black.design.pattern.responsibilitychain.auth;
// 处理类
public abstract class Handler {
// 下一处理类
protected Handler nextHandler;
// 处理
protected abstract void doHandle(UserInfo userInfo) ;
public void next(Handler h) {
this.nextHandler = h;
}
// 用于构建 handler 处理链
public static class Builder{
private Handler first;// 首节点
private Handler last;// 尾节点
// 设置下一节点
public Builder next(Handler handler) {
if(first == null ) {
// 如果 首节点是null 那么 handler 就是第一个节点
first = last = handler;
}
// 如果 首节点不是null 那么 handler 就加入到最后一个节点
last.next(handler);
last = handler;
return this;
}
public Handler build() {
// 每次返回链的首节点
return first;
}
}
}
package com.black.design.pattern.responsibilitychain.auth;
// 登录接口实现类
public class LoginServiceImpl implements LoginService {
public void login(String userName, String password) {
// 校验用户名密码是否为null
Handler vHandler = new ValidatorHandler();
// 登录
Handler loginHandler = new LoginHandler();
// 校验是否有权限
Handler authHandler = new AuthHandler();
// 构建 handler 处理链
Handler.Builder builder = new Handler.Builder();
builder.next(vHandler).next(loginHandler).next(authHandler);
builder.build().doHandle(new UserInfo(userName, password));
}
}
测试结果:
用户名和密码不为空,继续
登录成功!
允许操作