前言
责任链设计模式系列文章
责任链设计模式(一) - 定义及使用
责任链设计模式(二) - 使用场景
1. 定义?
使多个对象都有机会处理请求,将这些对象连成一条链子,并且沿着这条链子处理该请求,直到有对象处理它为止;
2. 举例说明
比如还是早期的微信登录,比如有3个用户系统的账号密码都可以登录,微信用户系统、qq用户系统、农药用户系统。
思路如下
1>:定义用户处理接口 IUserSystem,定义queryUserInfo(userName, userPwd)方法,用于根据用户名和密码查询用户信息;
2>:定义责任链设计模式的接口 IUserSystemHandler,用于获取下一个用户系统的handler;
3>:定义抽象处理者角色 AbsUserSystemHandler,让其实现上边两个接口,重写两个方法,获取下一个系统的getNextHandler()方法 和 设置下一个系统的 nextHandler()方法;
4>:让微信用户系统继承抽象类 AbsUserSystemHandler,让其实现 queryUserInfo(),查询的方式是:
a:首先是自己利用for循环查询,如果有返回userInfo信息,就直接返回;
b:如果没有,就调用 getNextHandler()获取下一个用户系统,然后调用nextHandler.queryUserInfo(),继续去查询用户信息,如果有就返回,如果没有就返回null即可;
qq用户系统、农药用户系统查询用户信息方式和4>一样,都是先遍历for循环,如果没有就让下一个用户系统查询;
3. 代码如下
1>:定义用户处理接口 IUserSystem,定义queryUserInfo(userName, userPwd)方法,用于根据用户名和密码查询用户信息
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/6/9 9:17
* Version 1.0
* Params:
* Description: 校验用户的处理接口
*/
public interface IUserSystem {
/**
* 根据用户名和密码查询用户信息
*/
public UserInfo queryUserInfo(String userName , String userPwd) ;
}
2>:定义责任链设计模式的接口 IUserSystemHandler,用于获取下一个用户系统的handler:
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/6/9 9:13
* Version 1.0
* Params:
* Description: 责任链设计模式 - 抽象处理者角色接口
*/
public interface IUserSystemHandler<T extends IUserSystemHandler> {
/**
* 获取下一个系统的handler
*/
void nextHandler(T systemHandler) ;
}
3>:定义抽象处理者角色 AbsUserSystemHandler,让其实现上边两个接口,重写两个方法,获取下一个系统的getNextHandler()方法 和 设置下一个系统的 nextHandler()方法:
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/6/9 9:11
* Version 1.0
* Params:
* Description: 责任链设计模式 - 抽象处理者角色
*/
public abstract class AbsUserSystemHandler implements IUserSystemHandler<AbsUserSystemHandler> , IUserSystem{
private AbsUserSystemHandler nextHandler ;
/**
* 获取下一个系统
*/
public AbsUserSystemHandler getNextHandler() {
return nextHandler;
}
/**
* 如果微信用户系统没有查到信息,就设置下一个系统,是qq用户系统
* 如果qq用户系统没有查到信息,就设置下一个系统,是农药用户系统
* 如果还有下一个用户系统,会去设置下一个系统...
*/
public void nextHandler(AbsUserSystemHandler nextHandler) {
this.nextHandler = nextHandler;
}
}
4>:让微信用户系统继承抽象类 AbsUserSystemHandler,让其实现 queryUserInfo(),查询的方式是:
a:首先是自己利用for循环查询,如果有返回userInfo信息,就直接返回;
b:如果没有,就调用 getNextHandler()获取下一个用户系统,然后调用nextHandler.queryUserInfo(),继续去查询用户信息,如果有就返回,如果没有就返回null即可;
qq用户系统、农药用户系统查询用户信息方式和4>一样,都是先遍历for循环,如果没有就让下一个用户系统查询;
微信用户系统如下:
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/6/3 11:10
* Version 1.0
* Params:
* Description: 微信的用户系统 - 数组存储 - 不需要暴露数组,直接暴露一个迭代器iterator()方法给外部即可
*/
public class WXUserSystem extends AbsUserSystemHandler{
UserInfo[] userInfos ;
public WXUserSystem(){
userInfos = new UserInfo[3] ;
userInfos[0] = new UserInfo("Novate","123456","001","男") ;
userInfos[1] = new UserInfo("景甜","123456","002","女") ;
userInfos[2] = new UserInfo("江疏影","123456","003","男") ;
}
/**
* 查询用户信息
* 首先是自己利用for循环遍历,看是否有userInfo信息:
* 如果有,就返回;
* 如果没有,就获取下一个用户系统,让下一个用户系统继续根据用户名和密码查询
*/
@Override
public UserInfo queryUserInfo(String userName, String userPwd) {
for (UserInfo userInfo : userInfos) {
if (userInfo.userName.equals(userName) && userInfo.userPwd.equals(userPwd)){
return userInfo ;
}
}
AbsUserSystemHandler nextHandler = getNextHandler();
if (nextHandler != null) {
return nextHandler.queryUserInfo(userName, userPwd);
}
return null ;
}
}
qq用户系统如下:
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/6/3 11:09
* Version 1.0
* Params:
* Description: QQ用户系统 - list集合存储 - 不需要暴露list集合,直接暴露一个迭代器iterator()方法给外部即可
*/
public class QQUserSystem extends AbsUserSystemHandler{
private List<UserInfo> userInfos ;
public QQUserSystem(){
userInfos = new ArrayList<>() ;
userInfos.add(new UserInfo("Novate","123456","001","男")) ;
userInfos.add(new UserInfo("王子文","123456","002","女")) ;
userInfos.add(new UserInfo("世道无情","123456","003","男")) ;
}
/**
* 查询用户信息
* 首先是自己利用for循环遍历,看是否有userInfo信息:
* 如果有,就返回;
* 如果没有,就获取下一个用户系统,让下一个用户系统继续根据用户名和密码查询
*/
@Override
public UserInfo queryUserInfo(String userName, String userPwd) {
for (UserInfo userInfo : userInfos) {
if (userInfo.userName.equals(userName) && userInfo.userPwd.equals(userPwd)){
return userInfo ;
}
}
AbsUserSystemHandler nextHandler = getNextHandler();
if (nextHandler != null) {
return nextHandler.queryUserInfo(userName, userPwd);
}
return null ;
}
}
农药用户系统如下:
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/6/9 9:26
* Version 1.0
* Params:
* Description: 农药用户系统
*/
public class NYUserSystem extends AbsUserSystemHandler {
private List<UserInfo> userInfos;
public NYUserSystem(){
userInfos = new ArrayList<>();
userInfos.add(new UserInfo("Novate","123456","001","男"));
userInfos.add(new UserInfo("王子文","123456","002","女"));
userInfos.add(new UserInfo("吴京","123456","003","男"));
}
/**
* 查询用户信息
* 首先是自己利用for循环遍历,看是否有userInfo信息:
* 如果有,就返回;
* 如果没有,就获取下一个用户系统,让下一个用户系统继续根据用户名和密码查询
*/
@Override
public UserInfo queryUserInfo(String userName, String userPwd) {
for (UserInfo userInfo : userInfos) {
if (userInfo.userName.equals(userName) && userInfo.userPwd.equals(userPwd)){
return userInfo ;
}
}
AbsUserSystemHandler nextHandler = getNextHandler();
if (nextHandler != null) {
return nextHandler.queryUserInfo(userName, userPwd);
}
return null ;
}
}
5>:测试类如下
/**
* Email: 2185134304@qq.com
* Created by Novate 2018/6/3 11:23
* Version 1.0
* Params:
* Description: 责任链设计模式写法
*/
public class Client {
public static void main(String[] args){
// 根据用户名和密码查询用户信息 ,
// 如果没有查询到,那么代表登录失败;如果查询到了,代表登录成功
QQUserSystem qqUserSystem = new QQUserSystem() ;
WXUserSystem wxUserSystem = new WXUserSystem() ;
NYUserSystem nyUserSystem = new NYUserSystem() ;
// 责任链设计模式,不断的获取下一个系统,直到最后一个系统为止
wxUserSystem.nextHandler(qqUserSystem);
qqUserSystem.nextHandler(nyUserSystem);
// 如果有数据,就返回;如果没有,就返回null
UserInfo userInfo = wxUserSystem.queryUserInfo("Novate", "123456");
// UserInfo{userName='Novate', userPwd='123456', userId='001', userSex='男'}
System.out.println(userInfo);
}
}
测试的流程是:
a:首先从微信用户系统根据用户名和密码查询,如果查询到信息,就返回;
b:如果没有查询到对应用户信息,就继续从qq用户系统查询,如果查询到信息,就返回;
c:如果没有查询到,就继续从农药中根据用户名和密码查询,如果查询到信息,就返回,如果没有就返回null;
如果以后有更多系统,只需要调用下一个用户系统即可;
wxUserSystem.nextHandler(qqUserSystem);
qqUserSystem.nextHandler(nyUserSystem);
在这里对应定义就是:
让微信系统、qq系统、农药系统和更多的系统,都有机会去查询用户信息,使用nextHandler()把这些对象连接成一条链子,并且沿着这条链子查询用户信息,直到有系统可以查询到用户信息为止;