地方网站推广,做网站的结论和心得,厦门建设厅查询网站,免费推广预期效果在现代的软件开发中#xff0c;程序低耦合、高复用、w易拓展、易维护 什么是责任链 责任链模式是一种行为设计模式#xff0c; 允许你将请求沿着处理者链进行发送。收到请求后#xff0c; 每个处理者均可对请求进行处理#xff0c; 或将其传递给链上的下个处理者。 使用场景…在现代的软件开发中程序低耦合、高复用、w易拓展、易维护 什么是责任链 责任链模式是一种行为设计模式 允许你将请求沿着处理者链进行发送。收到请求后 每个处理者均可对请求进行处理 或将其传递给链上的下个处理者。 使用场景
多条件流程判断权限控制ERP 系统流程审批总经理、人事经理、项目经理Java 过滤器的底层实现 Filter
| 反例
假设现在有一个闯关游戏进入下一关的条件是上一关的分数要高于 xx
游戏一共 3 个关卡进入第二关需要第一关的游戏得分大于等于 80进入第三关需要第二关的游戏得分大于等于 90
那么代码可以这样写
//第一关
public class FirstPassHandler { public int handler(){ System.out.println(第一关--FirstPassHandler); return 80; }
} //第二关
public class SecondPassHandler { public int handler(){ System.out.println(第二关--SecondPassHandler); return 90; }
} //第三关
public class ThirdPassHandler { public int handler(){ System.out.println(第三关--ThirdPassHandler这是最后一关啦); return 95; }
} //客户端
public class HandlerClient { public static void main(String[] args) { FirstPassHandler firstPassHandler new FirstPassHandler();//第一关 SecondPassHandler secondPassHandler new SecondPassHandler();//第二关 ThirdPassHandler thirdPassHandler new ThirdPassHandler();//第三关 int firstScore firstPassHandler.handler(); //第一关的分数大于等于80则进入第二关 if(firstScore 80){ int secondScore secondPassHandler.handler(); //第二关的分数大于等于90则进入第二关 if(secondScore 90){ thirdPassHandler.handler(); } } }
}那么如果这个游戏有 100 关我们的代码很可能就会写成这个样子
if(第1关通过){ // 第2关 游戏 if(第2关通过){ // 第3关 游戏 if(第3关通过){ //... } }
}这种代码不仅冗余并且当我们要将某两关进行调整时会对代码非常大的改动这种操作的风险是很高的。
| 初步改造
如何解决这个问题我们可以通过链表将每一关连接起来形成责任链的方式第一关通过后是第二关第二关通过后是第三关… 这样客户端就不需要进行多重 if 的判断了各个节点逻辑也清洗。
public class FirstPassHandler { /** * 第一关的下一关是 第二关 */ private SecondPassHandler secondPassHandler; public void setSecondPassHandler(SecondPassHandler secondPassHandler) { this.secondPassHandler secondPassHandler; } //本关卡游戏得分 private int play(){ return 80; } public int handler(){ System.out.println(第一关--FirstPassHandler); if(play() 80){ //分数80 并且存在下一关才进入下一关 if(this.secondPassHandler ! null){ return this.secondPassHandler.handler(); } } return 80; }
} public class SecondPassHandler { /** * 第二关的下一关是 第三关 */ private ThirdPassHandler thirdPassHandler; public void setThirdPassHandler(ThirdPassHandler thirdPassHandler) { this.thirdPassHandler thirdPassHandler; } //本关卡游戏得分 private int play(){ return 90; } public int handler(){ System.out.println(第二关--SecondPassHandler); if(play() 90){ //分数90 并且存在下一关才进入下一关 if(this.thirdPassHandler ! null){ return this.thirdPassHandler.handler(); } } return 90; }
} public class ThirdPassHandler { //本关卡游戏得分 private int play(){ return 95; } /** * 这是最后一关因此没有下一关 */ public int handler(){ System.out.println(第三关--ThirdPassHandler这是最后一关啦); return play(); }
} public class HandlerClient { public static void main(String[] args) { FirstPassHandler firstPassHandler new FirstPassHandler();//第一关 SecondPassHandler secondPassHandler new SecondPassHandler();//第二关 ThirdPassHandler thirdPassHandler new ThirdPassHandler();//第三关 firstPassHandler.setSecondPassHandler(secondPassHandler);//第一关的下一关是第二关 secondPassHandler.setThirdPassHandler(thirdPassHandler);//第二关的下一关是第三关 //说明因为第三关是最后一关因此没有下一关 //开始调用第一关 每一个关卡是否进入下一关卡 在每个关卡中判断 firstPassHandler.handler(); }
}| 缺点
每个关卡中都有下一关的成员变量并且是不一样的形成链很不方便代码的扩展性非常不好
|优化
既然每个关卡中都有下一关的成员变量并且是不一样的那么我们可以在关卡上抽象出一个父类或者接口然后每个具体的关卡去继承或者实现。示列
public abstract class AbstractHandler { /** * 下一关用当前抽象类来接收 */ protected AbstractHandler next; public void setNext(AbstractHandler next) { this.next next; } public abstract int handler();
} public class FirstPassHandler extends AbstractHandler{ private int play(){ return 80; } Override public int handler(){ System.out.println(第一关--FirstPassHandler); int score play(); if(score 80){ //分数80 并且存在下一关才进入下一关 if(this.next ! null){ return this.next.handler(); } } return score; }
} public class SecondPassHandler extends AbstractHandler{ private int play(){ return 90; } public int handler(){ System.out.println(第二关--SecondPassHandler); int score play(); if(score 90){ //分数90 并且存在下一关才进入下一关 if(this.next ! null){ return this.next.handler(); } } return score; }
} public class ThirdPassHandler extends AbstractHandler{ private int play(){ return 95; } public int handler(){ System.out.println(第三关--ThirdPassHandler); int score play(); if(score 95){ //分数95 并且存在下一关才进入下一关 if(this.next ! null){ return this.next.handler(); } } return score; }
} public class HandlerClient { public static void main(String[] args) { FirstPassHandler firstPassHandler new FirstPassHandler();//第一关 SecondPassHandler secondPassHandler new SecondPassHandler();//第二关 ThirdPassHandler thirdPassHandler new ThirdPassHandler();//第三关 // 和上面没有更改的客户端代码相比只有这里的set方法发生变化其他都是一样的 firstPassHandler.setNext(secondPassHandler);//第一关的下一关是第二关 secondPassHandler.setNext(thirdPassHandler);//第二关的下一关是第三关 //说明因为第三关是最后一关因此没有下一关 //从第一个关卡开始 firstPassHandler.handler(); }
}对于上面的请求链我们也可以把这个关系维护到配置文件中或者一个枚举中。示列
public enum GatewayEnum { // handlerId, 拦截者名称全限定类名preHandlerIdnextHandlerId API_HANDLER(new GatewayEntity(1, api接口限流, cn.dgut.design.chain_of_responsibility.GateWay.impl.ApiLimitGatewayHandler, null, 2)), BLACKLIST_HANDLER(new GatewayEntity(2, 黑名单拦截, cn.dgut.design.chain_of_responsibility.GateWay.impl.BlacklistGatewayHandler, 1, 3)), SESSION_HANDLER(new GatewayEntity(3, 用户会话拦截, cn.dgut.design.chain_of_responsibility.GateWay.impl.SessionGatewayHandler, 2, null)), ; GatewayEntity gatewayEntity; public GatewayEntity getGatewayEntity() { return gatewayEntity; } GatewayEnum(GatewayEntity gatewayEntity) { this.gatewayEntity gatewayEntity; }
} public class GatewayEntity { private String name; private String conference; private Integer handlerId; private Integer preHandlerId; private Integer nextHandlerId;
} public interface GatewayDao { /** * 根据 handlerId 获取配置项 * param handlerId * return */ GatewayEntity getGatewayEntity(Integer handlerId); /** * 获取第一个处理者 * return */ GatewayEntity getFirstGatewayEntity();
} public class GatewayImpl implements GatewayDao { /** * 初始化将枚举中配置的handler初始化到map中方便获取 */ private static MapInteger, GatewayEntity gatewayEntityMap new HashMap(); static { GatewayEnum[] values GatewayEnum.values(); for (GatewayEnum value : values) { GatewayEntity gatewayEntity value.getGatewayEntity(); gatewayEntityMap.put(gatewayEntity.getHandlerId(), gatewayEntity); } } Override public GatewayEntity getGatewayEntity(Integer handlerId) { return gatewayEntityMap.get(handlerId); } Override public GatewayEntity getFirstGatewayEntity() { for (Map.EntryInteger, GatewayEntity entry : gatewayEntityMap.entrySet()) { GatewayEntity value entry.getValue(); // 没有上一个handler的就是第一个 if (value.getPreHandlerId() null) { return value; } } return null; }
} public class GatewayHandlerEnumFactory { private static GatewayDao gatewayDao new GatewayImpl(); // 提供静态方法获取第一个handler public static GatewayHandler getFirstGatewayHandler() { GatewayEntity firstGatewayEntity gatewayDao.getFirstGatewayEntity(); GatewayHandler firstGatewayHandler newGatewayHandler(firstGatewayEntity); if (firstGatewayHandler null) { return null; } GatewayEntity tempGatewayEntity firstGatewayEntity; Integer nextHandlerId null; GatewayHandler tempGatewayHandler firstGatewayHandler; // 迭代遍历所有handler以及将它们链接起来 while ((nextHandlerId tempGatewayEntity.getNextHandlerId()) ! null) { GatewayEntity gatewayEntity gatewayDao.getGatewayEntity(nextHandlerId); GatewayHandler gatewayHandler newGatewayHandler(gatewayEntity); tempGatewayHandler.setNext(gatewayHandler); tempGatewayHandler gatewayHandler; tempGatewayEntity gatewayEntity; } // 返回第一个handler return firstGatewayHandler; } /** * 反射实体化具体的处理者 * param firstGatewayEntity * return */ private static GatewayHandler newGatewayHandler(GatewayEntity firstGatewayEntity) { // 获取全限定类名 String className firstGatewayEntity.getConference(); try { // 根据全限定类名加载并初始化该类即会初始化该类的静态段 Class? clazz Class.forName(className); return (GatewayHandler) clazz.newInstance(); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { e.printStackTrace(); } return null; } } public class GetewayClient { public static void main(String[] args) { GetewayHandler firstGetewayHandler GetewayHandlerEnumFactory.getFirstGetewayHandler(); firstGetewayHandler.service(); }
}