学校网站建设介绍,介绍网页设计,企业网站设计经典案例,网站建设和邮箱的关联责任链模式
责任链模式#xff08;Chain of Responsibility Pattern#xff09;是一种行为型设计模式#xff0c;它用于将请求的发送者和接收者解耦#xff0c;使多个对象都有机会处理请求。这种模式建立在一个处理对象的链上#xff0c;每个处理对象都可以选择处理请求或…责任链模式
责任链模式Chain of Responsibility Pattern是一种行为型设计模式它用于将请求的发送者和接收者解耦使多个对象都有机会处理请求。这种模式建立在一个处理对象的链上每个处理对象都可以选择处理请求或者将请求传递给链上的下一个处理对象。
1、责任链模式角色
在 Java 中责任链模式的实现通常包括以下几个要素
抽象处理者Handler定义一个处理请求的接口通常包括一个处理方法例如handleRequest()和一个设置下一个处理者的方法例如setNextHandler()。抽象处理者可以是一个接口或者抽象类。具体处理者ConcreteHandler实现抽象处理者接口具体处理不同的请求。如果当前处理者无法处理请求它可以将请求传递给下一个处理者。责任链Chain ofResponsibility将一系列的处理者连接成一个链形成处理请求的链式结构。通常在客户端代码中构建这个责任链并将请求从链的开头传递给第一个处理者。 2、责任链模式适用业务场景
日志记录系统在系统中实现日志记录功能时可以使用责任链模式。不同的日志级别如调试、信息、警告、错误可以由不同的处理器来处理从而根据需要将日志记录到不同的目标文件、数据库、控制台等。审批流程在企业应用中审批流程可能涉及多个层级的审批每个层级的审批者都可以决定是否通过审批。责任链模式可以用于构建这样的审批流程其中每个处理器代表一个审批者如果一个审批者无法处理请求将传递给下一个审批者。安全认证在安全认证中可以使用责任链模式来实现多层级的认证机制。每个认证处理器可以负责一个特定的认证方法如用户名密码、指纹、令牌等。如果一个认证处理器无法通过认证系统可以继续尝试下一个处理器。HTTP 请求处理在 Web 应用程序中HTTP 请求处理可以分成多个环节例如身份验证、授权、输入验证、缓存等。责任链模式可以用于将每个环节拆分成一个处理器并将请求从一个处理器传递到下一个处理器。异常处理链在处理异常时可能需要一系列处理步骤来处理不同类型的异常。责任链模式可以用于将异常处理逻辑分解成多个处理器每个处理器负责处理一种类型的异常。请求过滤器在 Web 开发中请求过滤器可以用于对请求进行预处理例如请求参数验证、安全检查等。责任链模式可以用于将不同的过滤逻辑拆分成多个处理器依次对请求进行处理。游戏闯关系统在游戏中角色的闯关系统可以采用责任链模式。每层关卡可以由不同的处理器来处理如果一个处理器处理完成当前关卡结果打到过关条件系统可以使用下一个处理器进行下一关处理。
总之责任链模式在任何需要将处理逻辑拆分成独立步骤并且这些步骤可以灵活组合的情况下都是有用的。它帮助减少耦合使代码更加可扩展和可维护。
3、游戏闯关系统责任链模式的应用
需求描述
假设现在有一个闯关游戏进入下一关的条件是上一关的分数要高于 xx
游戏一共 3 个关卡 进入第二关需要第一关的游戏得分大于等于 90 进入第三关需要第二关的游戏得分大于等于 80
普通业务代码实现
//第一关
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();//第一关的分数大于等于90则进入第二关if(firstScore 90){int secondScore secondPassHandler.handler();//第二关的分数大于等于80则进入第二关if(secondScore 80){thirdPassHandler.handler();}}}
}那么如果这个游戏有 99 关我们的代码很可能就会写成这个样子
if(第1关通过){// 第2关 游戏if(第2关通过){// 第3关 游戏if(第3关通过){// 第4关 游戏if(第4关通过){// 第5关 游戏if(第5关通过){// 第6关 游戏if(第6关通过){//...}}} }}
}这种代码不仅冗余并且当我们要将某两关进行调整时会对代码非常大的改动这种操作的风险是很高的因此该写法非常糟糕。
责任链改造代码
如何解决这个问题我们可以通过链表将每一关连接起来形成责任链的方式第一关通过后是第二关第二关通过后是第三关…
这样客户端就不需要进行多重 if 的判断了
public abstract class Handler {/*** 下一关用当前抽象接口来接收*/protected Handler next;public void setNext(Handler next) {this.next next;}public abstract int handler();
} public class FirstPassHandler extends Handler{final int firstPassScore 90;private int play(){return firstPassScore;}Overridepublic int handler(){System.out.println(第一关--FirstPassHandler);int score play();if(score firstPassScore){//分数firstPassScore 并且存在下一关才进入下一关if(this.next ! null){return this.next.handler();}}return score;}
}
package com.lf.java.designpattern.chain;public class SecondPassHandler extends Handler{final int SecondPassScore 80;private int play(){return SecondPassScore;}public int handler(){System.out.println(第二关--SecondPassHandler);int score play();if(score SecondPassScore){//分数SecondPassScore 并且存在下一关才进入下一关if(this.next ! null){return this.next.handler();}}return score;}
}package com.lf.java.designpattern.chain;public class ThirdPassHandler extends Handler{final int SecondPassScore 70;private int play(){return SecondPassScore;}public int handler(){System.out.println(第三关--ThirdPassHandler);int score play();if(score SecondPassScore){//分数SecondPassScore 并且存在下一关才进入下一关if(this.next ! null){return this.next.handler();}}return score;}
}
package com.lf.java.designpattern.chain;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();}
}改造完成的代码请求会从链的开头传递到每个处理器根据请求的内容每个处理器都可以选择处理请求或者将请求传递给下一个处理器。这样的设计使得责任链可以根据需要动态地调整和扩展。
但是还不能自动化的添加对应的链之间的关系。
责任链工厂改造代码
对于上面的请求链我们也可以把这个关系维护到配置文件中或者一个枚举中。将使用枚举来动态的配置请求链并且将每个请求者形成一条调用链。
Data
AllArgsConstructor
NoArgsConstructor
EqualsAndHashCode
ToString
public class PassEntity {/** 处理器顺序id */private Integer handlerId;/** 业务处理器名称*/private String name;/** 全限定类名 */private String conference;/** 前置处理器 */private Integer preHandlerId;/** 前置处理器 */private Integer nextHandlerId;
}public enum PassEnum {// handlerId, 拦截者名称全限定类名preHandlerIdnextHandlerIdAPI_HANDLER(new PassEntity(1, 第一关, com.lf.java.design.pattern.chain.FirstPassHandler, null, 2)),BLACKLIST_HANDLER(new PassEntity(2, 第二关, com.lf.java.design.pattern.chain.SecondPassHandler, 1, 3)),SESSION_HANDLER(new PassEntity(3, 第三关, com.lf.java.design.pattern.chain.ThirdPassHandler, 2, null)),;PassEntity passEntity;public PassEntity getPassEntity() {return passEntity;}PassEnum(PassEntity passEntity) {this.passEntity passEntity;}
}public interface IPassService {/*** 根据 handlerId 获取配置项* param handlerId* return*/PassEntity getPassEntity(Integer handlerId);/*** 获取第一个处理者* return*/PassEntity getFirstPassEntity();
}package com.lf.java.designpattern.chain;import java.util.HashMap;
import java.util.Map;public class PassServiceImpl implements IPassService {/*** 初始化将枚举中配置的handler初始化到map中方便获取*/private static MapInteger, PassEntity passEntityMap new HashMap();static {PassEnum[] values PassEnum.values();for (PassEnum value : values) {PassEntity passEntity value.getPassEntity();passEntityMap.put(passEntity.getHandlerId(), passEntity);}}Overridepublic PassEntity getPassEntity(Integer handlerId) {return passEntityMap.get(handlerId);}Overridepublic PassEntity getFirstPassEntity() {for (Map.EntryInteger, PassEntity entry : passEntityMap.entrySet()) {PassEntity value entry.getValue();// 没有上一个handler的就是第一个if (value.getPreHandlerId() null) {return value;}}return null;}
}package com.lf.java.designpattern.chain;public class PassHandlerEnumFactory {private static IPassService passService new PassServiceImpl();// 提供静态方法获取第一个handlerpublic static Handler getFirstPassHandler() {PassEntity firstPassEntity passService.getFirstPassEntity();Handler firstPassHandler newPassHandler(firstPassEntity);if (firstPassHandler null) {return null;}PassEntity tempPassEntity firstPassEntity;Integer nextHandlerId null;Handler tempPassHandler firstPassHandler;// 迭代遍历所有handler以及将它们链接起来while ((nextHandlerId tempPassEntity.getNextHandlerId()) ! null) {PassEntity PassEntity passService.getPassEntity(nextHandlerId);Handler PassHandler newPassHandler(PassEntity);tempPassHandler.setNext(PassHandler);tempPassHandler PassHandler;tempPassEntity PassEntity;}// 返回第一个handlerreturn firstPassHandler;}/*** 反射实体化具体的处理者* param firstPassEntity* return*/private static Handler newPassHandler(PassEntity firstPassEntity) {// 获取全限定类名String className firstPassEntity.getConference();try {// 根据全限定类名加载并初始化该类即会初始化该类的静态段Class? clazz Class.forName(className);return (Handler) clazz.newInstance();} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {e.printStackTrace();}return null;}}测试业务类
public class PassHandlerClient {public static void main(String[] args) {Handler firstPassHandler PassHandlerEnumFactory.getFirstPassHandler();firstPassHandler.handler();}
}运行结果
第一关--FirstPassHandler
第二关--SecondPassHandler
第三关--ThirdPassHandler这样通过动态的配置请求链就可以自动将每个请求者形成一条调用链。
还有更为复杂的链的形成比如业务的链里面有复合链而复合链又是普通的功能链组成的。这种责任链工厂方式更能充分体现出代码设计优势。