文章目录
一、责任链模式简介
二、责任链模式相关设计模式
三、责任链模式 代码示例
1、用户账户类
2、校验器父类
3、用户名校验器
4、密码校验器
5、电话号码校验器
6、运行测试
一、责任链模式简介
责任链模式 , 又称为 职责链模式 ;
责任链模式定义 : 为 请求 创建一个接收该 请求对象 的 链 , 链条中每个元素都是一个对象 ;
责任链模式类型 : 行为型 ;
责任链模式 适用场景 : 一个 请求 的 处理 , 需 要多个对象 中的 一个或若干个对象 协作进行处理 ;
责任链模式 优点 :
① 解耦 : 请求的 发送者 和 接收者 解耦 ; 接收者 是 请求的处理者 ;
② 动态组合 : 责任链 可以 动态组合 , 使用配置 设置责任链的 顺序及 是否出现 ; 可以随时对责任链排序 , 随时增加拆除责任链中的某个请求对象 ;
责任链模式 缺点 :
① 性能 : 如果 责任链 太长 , 或责任链中请求的 处理时间过长 , 可能会 影响性能 ;
② 个数 : 责任链 可能过多 ;
二、责任链模式相关设计模式
责任链模式 与 状态模式 比较 :
在 责任链模式 中 , 并 不指定 下一个处理的 请求对象 是哪个 ; 责任链 中 链条顺序 可以 任意组合排序 ;
在 状态模式 中 , 需要让 每个 状态 知道下一个需要处理的状态是谁 ;
三、责任链模式 代码示例
需求 :
OA 中审批流程 , 需要 组长 , 经理 , 总监 审批请求 ;
账号注册时进行校验 , 先后校验 账号 , 密码 , 手机号 等 ;
使用责任链模式实现上述操作 , 可以消除很多 if else 分支 , 增加功能的扩展性 , 如果在责任链条中添加一个请求 , 只需要新建一个类即可 , 这个类就是责任链中的请求元素 ; 可以选择性使用一个或多个或所有的请求对象 ;
这里以账户校验为示例 : 使用 责任链 , 校验用户账户的 账号 , 密码 , 手机号 等信息 ;
1、用户账户类
package responsibility; /** * 用户账户信息 * 包含 : 账号 , 密码 , 电话号码 */ public class UserAccount { private String userName; private String password; private String phoneNumber; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } }
2、校验器父类
校验类的父类 , 校验账号 , 校验密码 , 校验手机号 的请求类都需要 继承该类 ;
封装请求对象 : 责任链的核心是 请求对象 中 包含一个自己 , 包含一个与自己相同类型的对象 ; 责任链模式中的 校验器 封装一个 校验器 本身 , 使用 protected 修饰的目的是让子类可以获取到该类 ;
设置下一个请求对象 : 每个请求对象中 , 设置下一个请求对象 , 组成链式结构 ;
请求过程 : 抽象方法 , 需要子类实现 , 主要 实现 请求对象 需要的具体的业务逻辑 , 如校验 , 审批 等 ;
package responsibility; /** * 校验类的父类 * 校验账号 , 校验密码 , 校验手机号 的请求类都需要继承该类 */ public abstract class Verify { /** * 责任链的核心是类中包含一个自己 * 包含一个与自己相同类型的对象 * 责任链模式中的 校验器 封装一个 校验器 本身 * 使用 protected 修饰的目的是让子类可以获取到该类 */ protected Verify verify; /** * 设置下一个校验器 * @param verify */ public void setNextVerify(Verify verify) { this.verify = verify; } /** * 校验过程 * 需要子类进行实现 */ public abstract void deploy(UserAccount userAccount); }
3、用户名校验器
package responsibility; import com.sun.xml.internal.ws.util.StringUtils; /** * 校验用户名称 */ public class UserNameVerify extends Verify{ @Override public void deploy(UserAccount userAccount) { if (userAccount.getUserName() != null){ System.out.println("用户名校验通过"); // 获取下一个验证器 if (verify != null) { verify.deploy(userAccount); } } else { System.out.println("用户名校验未通过"); } } }
4、密码校验器
package responsibility; /** * 校验密码 */ public class PasswordVerify extends Verify{ @Override public void deploy(UserAccount userAccount) { if (userAccount.getPassword() != null){ System.out.println("密码校验通过"); // 获取下一个验证器 if (verify != null) { verify.deploy(userAccount); } } else { System.out.println("密码校验未通过"); } } }
5、电话号码校验器
package responsibility; /** * 校验手机号 */ public class PhoneVerify extends Verify{ @Override public void deploy(UserAccount userAccount) { if (userAccount.getPhoneNumber() != null){ System.out.println("手机号校验通过"); // 获取下一个验证器 if (verify != null) { verify.deploy(userAccount); } } else { System.out.println("手机号校验未通过"); } } }
6、运行测试
package responsibility; public class Main { public static void main(String[] args) { UserNameVerify userNameVerify = new UserNameVerify(); PasswordVerify passwordVerify = new PasswordVerify(); PhoneVerify phoneVerify = new PhoneVerify(); UserAccount userAccount = new UserAccount(); userAccount.setUserName("username"); userAccount.setPassword("123456"); userAccount.setPhoneNumber("13888888888"); // 创建职责链 userNameVerify.setNextVerify(passwordVerify); passwordVerify.setNextVerify(phoneVerify); // 开始校验 , 执行职责链 userNameVerify.deploy(userAccount); } }
运行结果 :
————————————————