设计模式之责任链模式详解(定义、优缺点、应用场景、实例类图)
时间:2024-12-09 来源:互联网 标签: PHP教程
责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。责任链模式通过将多个处理器(处理对象)以链式结构连接起来,使得请求沿着这条链传递,直到有一个处理器处理该请求为止。责任链模式允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
一、责任链模式的介绍
意图
允许将请求沿着处理者链传递,直到请求被处理为止。
主要解决的问题
解耦请求发送者和接收者,使多个对象都有可能接收请求,而发送者不需要知道哪个对象会处理它。
使用场景
当有多个对象可以处理请求,且具体由哪个对象处理由运行时决定时。
当需要向多个对象中的一个提交请求,而不想明确指定接收者时。
实现方式
定义处理者接口:所有处理者必须实现同一个接口。
创建具体处理者:实现接口的具体类,包含请求处理逻辑和指向链中下一个处理者的引用。
关键代码
Handler接口:定义一个方法用于处理请求。
ConcreteHandler类:实现Handler接口,包含请求处理逻辑和对下一个处理者的引用。
结构
主要涉及到以下几个核心角色:
抽象处理者(Handler):
定义一个处理请求的接口,通常包含一个处理请求的方法(如 handleRequest)和一个指向下一个处理者的引用(后继者)。
具体处理者(ConcreteHandler):
实现了抽象处理者接口,负责处理请求。如果能够处理该请求,则直接处理;否则,将请求传递给下一个处理者。
客户端(Client):
创建处理者对象,并将它们连接成一条责任链。通常,客户端只需要将请求发送给责任链的第一个处理者,无需关心请求的具体处理过程。
应用实例
击鼓传花:游戏中的传递行为,直到音乐停止。
事件冒泡:在JavaScript中,事件从最具体的元素开始,逐级向上传播。
Web服务器:如Apache Tomcat处理字符编码,Struts2的拦截器,以及Servlet的Filter。
二、责任链模式的优缺点
优点
降低耦合度:发送者和接收者之间解耦。
简化对象:对象不需要知道链的结构。
灵活性:通过改变链的成员或顺序,动态地新增或删除责任。
易于扩展:增加新的请求处理类很方便。
缺点
请求未被处理:不能保证请求一定会被链中的某个处理者接收。
性能影响:可能影响系统性能,且调试困难,可能导致循环调用。
难以观察:运行时特征不明显,可能妨碍除错。
三、责任链模式的使用建议
在处理请求时,如果有多个潜在的处理者,考虑使用责任链模式。
确保链中的每个处理者都明确知道如何传递请求到链的下一个环节。
在Java Web开发中,责任链模式有广泛应用,如过滤器链、拦截器等。
四、责任链模式的实现
我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。
步骤 1:创建抽象的记录器类。
AbstractLogger.java
publicabstractclassAbstractLogger{
publicstaticintINFO=1;
publicstaticintDEBUG=2;
publicstaticintERROR=3;
protectedintlevel;
//责任链中的下一个元素
protectedAbstractLoggernextLogger;
publicvoidsetNextLogger(AbstractLoggernextLogger){
this.nextLogger=nextLogger;
}
publicvoidlogMessage(intlevel,Stringmessage){
if(this.level<=level){
write(message);
}
if(nextLogger!=null){
nextLogger.logMessage(level,message);
}
}
abstractprotectedvoidwrite(Stringmessage);
}
步骤 2:创建扩展了该记录器类的实体类。
ConsoleLogger.java
publicclassConsoleLoggerextendsAbstractLogger{
publicConsoleLogger(intlevel){
this.level=level;
}
@Override
protectedvoidwrite(Stringmessage){
System.out.println("StandardConsole::Logger:"+message);
}
}
ErrorLogger.java
publicclassErrorLoggerextendsAbstractLogger{
publicErrorLogger(intlevel){
this.level=level;
}
@Override
protectedvoidwrite(Stringmessage){
System.out.println("ErrorConsole::Logger:"+message);
}
}
FileLogger.java
publicclassFileLoggerextendsAbstractLogger{
publicFileLogger(intlevel){
this.level=level;
}
@Override
protectedvoidwrite(Stringmessage){
System.out.println("File::Logger:"+message);
}
}
步骤 3:创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。
ChainPatternDemo.java
publicclassChainPatternDemo{
privatestaticAbstractLoggergetChainOfLoggers(){
AbstractLoggererrorLogger=newErrorLogger(AbstractLogger.ERROR);
AbstractLoggerfileLogger=newFileLogger(AbstractLogger.DEBUG);
AbstractLoggerconsoleLogger=newConsoleLogger(AbstractLogger.INFO);
errorLogger.setNextLogger(fileLogger);
fileLogger.setNextLogger(consoleLogger);
returnerrorLogger;
}
publicstaticvoidmain(String[]args){
AbstractLoggerloggerChain=getChainOfLoggers();
loggerChain.logMessage(AbstractLogger.INFO,"Thisisaninformation.");
loggerChain.logMessage(AbstractLogger.DEBUG,
"Thisisadebuglevelinformation.");
loggerChain.logMessage(AbstractLogger.ERROR,
"Thisisanerrorinformation.");
}
}
步骤 4:执行程序,输出结果:
StandardConsole::Logger:Thisisaninformation.
File::Logger:Thisisadebuglevelinformation.
StandardConsole::Logger:Thisisadebuglevelinformation.
ErrorConsole::Logger:Thisisanerrorinformation.
File::Logger:Thisisanerrorinformation.
StandardConsole::Logger:Thisisanerrorinformation.
以上就是php小编整理的全部内容,希望对您有所帮助,更多相关资料请查看php教程栏目。
-
永劫无间多少钱一个红 2024-12-20
-
永劫无间多少钱开一个箱子 2024-12-20
-
阿瑞斯病毒2火铳弹药怎么获得?阿瑞斯病毒2火铳弹药获得方法 2024-12-19
-
阿瑞斯病毒2哈士奇在哪?阿瑞斯病毒2哈士奇获得方法 2024-12-19
-
寻道大千反击流阵容推荐 2024-12-19
-
和平精英性别怎么换?和平精英性别转换方法 2024-12-19