一、简介
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,用于将请求的发送者与接收者解耦,使多个处理对象都有机会处理该请求。这些处理对象通过形成一条链式结构依次处理请求,直到某个对象能够完成处理或处理链结束。
责任链模式的核心思想是:将多个可能处理请求的对象连接成一条链,沿着链传递请求,直至某个处理对象处理它或链的末端。
应用场景
- 请求需要被多个对象处理:比如击鼓传花、事件冒泡机制、权限校验、日志记录等。
- 请求的处理逻辑需要灵活扩展:可以动态地增加或移除处理器。
- 避免请求的发送者和接收者之间的强耦合:发送者无需指定接收者,接收者可以灵活变化。
二、优缺点
优点
- 请求解耦:请求发送者和处理者解耦,降低代码耦合度。
- 灵活性高:可以动态组合和扩展处理链。
- 单一职责:每个处理器只关注自身的逻辑,符合开闭原则。
缺点
- 性能问题:如果链很长,可能会影响性能。
- 调试困难:请求的最终处理者不容易追踪,可能需要额外的日志记录。
- 请求未被处理:不能保证请求一定会被链中的某个处理者接收。
三、实际应用
场景
需求:针对不同用户群体设计多种校验规则:
- A群体:仅需校验手机验证码。
- B群体:需同时校验手机验证码和用户年龄。
要求根据用户群体的不同动态应用对应的校验规则,实现灵活性和扩展性。
代码实现:
步骤一:构造handler
java">public abstract class AbstractCheckHandler {public abstract void handler(CheckVO checkVO);public abstract int getCode();
}
步骤二 实现handler 进行不同的规则校验
java">public class PhoneCheckHandler extends AbstractCheckHandler {@Overridepublic void handler(CheckVO checkVO) {if (checkVO.getVerificationCode() == null) {throw new RuntimeException("验证码不能为空!!");}if (!Integer.valueOf("0000").equals(checkVO.getVerificationCode())) {throw new RuntimeException("验证码错误!!");}}@Overridepublic int getCode() {return 1;}
}
java">public class UserCheckHandler extends AbstractCheckHandler {private static Integer LEGAL_AGE = 18;@Overridepublic void handler(CheckVO checkVO) {if (checkVO.getUserId() == null) {throw new RuntimeException("用户不能为空");}if (LEGAL_AGE >= checkVO.getAge()) {throw new RuntimeException("用户未满十八岁");}}@Overridepublic int getCode() {return 0;}
}
步骤三 指定链路的传递方式 通过codeList进行控制
java">
public class CheckHandlerExecution {private final List<AbstractCheckHandler> handlers;public CheckHandlerExecution(){this.handlers = new ArrayList<>();this.handlers.add(new UserCheckHandler());this.handlers.add(new PhoneCheckHandler());}public CheckHandlerExecution(List<AbstractCheckHandler> handlers) {this.handlers = handlers;}public void handle(List<Integer> codeList, CheckVO checkVO) {for (AbstractCheckHandler handler : handlers) {int code = handler.getCode();if (codeList.contains(code)) {handler.handler(checkVO);}}}
}
步骤四 代码验证 针对不同用户群体通过list中的code进行控制校验 ,list可以配置在数据库中实现手动配置,从而进行动态校验
java">public class CorCheckTest {public static void main(String[] args) {CheckVO vo = new CheckVO();vo.setAge(16);vo.setUserId(123456);vo.setAreaCode("+86");vo.setVerificationCode(0000);CheckHandlerExecution execution = new CheckHandlerExecution();// 只执行手机号验证execution.handle(Arrays.asList(1), vo);// 同时执行手机号和用户年龄验证execution.handle(Arrays.asList(0, 1), vo);}
}