最近在做一个数据校验的功能,需要校验的东西很多,有的从数据库中查询,有的是固定的数值校验,有的是数据类型校验, 如果通过ifelse来写,也是没问题的。
但,为了代码的优雅和可扩展性,我选择尝试一下责任链模式,责任链模式的核心是 解决一组服务中的先后执行处理关系 。
责任链模式(Chain of Responsibility Pattern)是将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。当一个请求从链式的首端发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。属于行为型模式。
减少大量ifelse;
逻辑清晰明了,添加删除节点、改变节点顺序方便快捷;
请求与处理解耦;
请求处理者只需关注自己感兴趣的请求,对于不感兴趣的请求,直接转发给下一级节点对象;
易于扩展新的请求处理类,符合开闭原则;
责任链太长或处理时间过长,会影响整体性能。
如果需要判断的东西较多,容易造成类保证;
如果每个判断逻辑较简单,可能会造成一个类只做一个小小的数值判断,哈哈;
如果节点对象存在循环链接,可能会造成死循环;
对实体类程序员Programmer的数据进行校验,校验名字、项目、项目完成时间。
力求通过最简单的代码,通俗易懂的讲解责任链模式。
- <pre class="prettyprint hljs java" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">package com.guor.bean;
-
- import lombok.Data;
-
- import java.util.Date;
-
- @Data
- public class Programmer {
- // 姓名
- private String name;
- // 项目
- private String project;
- // 模块
- private String module;
- // 进度
- private double schedule;
- // 计划完成时间
- private Date completePlanTime;
- // 详细信息
- private String info;
- }
class="prettyprint hljs kotlin" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">package com.guor.chain;
-
- import com.guor.bean.Programmer;
-
- public class Check {
-
- public boolean programmerCheck(Programmer programmer){
-
- if(!"公众号".equals(programmer.getProject())){
- return false;
- }
-
- if(!"哪吒编程".equals(programmer.getName())){
- return false;
- }
-
- if(!programmer.getInfo().equals("公众号哪吒编程,定期分享Java干货,还有不定期的送书活动,包邮到你家,哈哈")){
- return false;
- }
-
- return true;
- }
- }
一堆ifelse安排上,代码还是比较清晰易懂的,再有新的判断,就继续添加ifelse就完了。
这部分是责任链模式的核心代码,重点在于通过next获取下一个节点。
定义一个抽象方法doHandler供子类去实现,实现不同的业务逻辑。
class="prettyprint hljs kotlin" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">package com.guor.chain;
-
- import com.guor.bean.Programmer;
-
- public abstract class Handler<T> {
-
- protected Handler next;
-
- private void next(Handler next) {
- this.next = next;
- }
-
- public abstract boolean doHandler(Programmer programmer);
-
- public static class Builder<T> {
- private Handler
head; - private Handler
tail; -
- public Builder
addHandler(Handler handler) { - if (this.head == null) {
- this.head = this.tail = handler;
- return this;
- }
- this.tail.next(handler);
- this.tail = handler;
- return this;
- }
-
- public Handler
build() { - return this.head;
- }
- }
- }
class="prettyprint hljs scala" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">package com.guor.chain;
-
- import com.guor.bean.Programmer;
-
- /**
- * 校验项目名称
- */
- public class ProjectHandler extends Handler {
-
- @Override
- public boolean doHandler(Programmer programmer) {
-
- if(!"公众号".equals(programmer.getProject())){
- return false;
- }
-
- if(null == next){
- return true;
- }
-
- return next.doHandler(programmer);
- }
- }
class="prettyprint hljs scala" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">package com.guor.chain;
-
- import com.guor.bean.Programmer;
-
- /**
- * 校验名字
- */
- public class NameHandler extends Handler {
-
- @Override
- public boolean doHandler(Programmer programmer) {
-
- if(!"哪吒编程".equals(programmer.getName())){
- return false;
- }
-
- if(null == next){
- return true;
- }
-
- return next.doHandler(programmer);
- }
- }
class="prettyprint hljs scala" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto;">package com.guor.chain;
-
- import com.guor.bean.Programmer;
-
- /**
- * 校验活动细节
- */
- public class InfoHandler extends Handler {
-
- @Override
- public boolean doHandler(Programmer programmer) {
-
- if(!programmer.getInfo().contains("扫描文末二维码,关注公众号哪吒编程,定期分享Java干货,还有不定期的送书活动,包邮到你家")){
- return false;
- }
-
- if(null == next){
- return true;
- }
-
- return next.doHandler(programmer);
- }
- }

责任链模式的设计,可以方便的进行扩展和维护,去掉了低俗的ifelse代码。
实际项目中的数据校验要复杂的多,还有一些审批流程、付款流程,都可以通过责任链模式进行改造,非常好用!
很多人觉得设计模式很简单,但是,能够熟练的将设计模式应用在自己的项目中,将各模块、功能规划的井井有条,运用的炉火纯青、恰到好处,真的很难。反复阅读,仔细体会。