前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【设计模式】行为型模式-第 3 章第 1 讲【责任链模式】

【设计模式】行为型模式-第 3 章第 1 讲【责任链模式】

作者头像
跟着飞哥学编程
发布2022-12-02 15:51:52
2660
发布2022-12-02 15:51:52
举报

目录

1、责任链模式的概念

1.1、百度百科对责任链的定义

1.2、责任链模式

2、责任链模式的作用

3、实现

3.1、责任链模式的通用类图,如下图 1-1:

3.2、代码实现案例

 4、责任链的优缺点

4.1、优点

4.2、缺点

5、责任链模式的应用场景 

6、结语


前言

这一章节主要介绍行为型模式

上一章节,我们介绍的是创建型模式,主要关注对象的创建,而这一章节的行为型模式主要关注对象交互通信控制流

大多数行为型模式都基于组合委托而不是继承。

接下来我们将在这一章节中讲解以下行为型模式:

  • 责任链模式
  • 命令模式
  • 解释器模式
  • 迭代器模式
  • 观察者模式
  • 中介者模式
  • 备忘录模式
  • 状态模式
  • 策略模式
  • 模板方法模式
  • 空对象模式
  • 访问者模式

1、责任链模式的概念

1.1、百度百科对责任链的定义

责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。


1.2、责任链模式

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。

计算机软件是用来处理信息的,有多种不同的方式来组织和处理信息。之前我们提过设计模式需要遵循的原则,在面向对象编程中,我们应该赋予一个类单一职责,从而使得类容易维护和扩展。

设想一个场景,需要对一批从客户端来的数据进行多种不同的操作,我们会使用多个不同的类负责不同的操作,而不是使用一个类集成所有的操作,这样做能让代码松耦合且简洁。

这些类被称为处理器,第一个处理器会接收请求,如果它需要执行操作则会进行一次调用,如果不需要则会传递给第二个处理器。类似地,第二个处理器确认并将请求传递给责任链中下一个处理器。

2、责任链模式的作用

目的:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,如果链上当前处理器可以处理,就处理,不能处理,就把请求传递给下一个处理器,就这样直到有对象处理它为止。 

主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

3、实现

3.1、责任链模式的通用类图,如下图 1-1:

图 1-1 

图1-1中包含以下三个类:

Client(客户端):客户端是使用责任链模式的应用程序的主要结构。它的职责是实例化一个处理器的链,然后在第一个对象中调用 handleRequest 方法。

Handler(处理器):这是一个抽象类,提供给所有实际处理器进行继承。它拥有一个 HandleRequest 方法,用来接收需要处理的请求。

ConcreteHandler(具体处理器):这是一个实现了 handleRequest 方法的具体类。每一个具体处理器都维持一个引用,指向链中下一个具体处理器,需要检查它自身是否能处理这个请求,如果不能处理就会把请求传递给链中的下一个具体处理器。

3.2、代码实现案例

我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。

先来看一张日志记录的类图结构,如图1-2:

 图1-2

 1)先来创建一个抽象处理器类 AbstaractLogger

AbstractLogger.java

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.chainOfResponsibilityPattern;
/**
 * 
 * @Date 2022年10月5日
 * @author zhaoYanFei
 *
 */
public abstract class AbstractLogger {

	public static int INFO = 1;
	public static int DEBUG = 2;
	public static int ERROR = 3;
	 
	protected int level;
	 
	//责任链中的下一个元素
	protected AbstractLogger nextLogger;
	 
	public void setNextLogger(AbstractLogger nextLogger){
		this.nextLogger = nextLogger;
	}
	 
	public void logMessage(int level, String message){
	     if(this.level <= level){
	         write(message);
	     }
	     if(nextLogger !=null){
	    	nextLogger.logMessage(level, message);
	     }
   }
	 
   abstract protected void write(String message);
	
}

这个基类中我们有设置下一个责任处理器的方法 setNextLogger 方法。

 2)创建一个继承了基类的 对象处理器 ConsoleLogger

ConsoleLogger .java

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.chainOfResponsibilityPattern;

public class ConsoleLogger extends AbstractLogger {

	public ConsoleLogger(int level){
		this.level = level;
	}
	
	@Override
	protected void write(String message) {
		System.out.println("Standard Console::Logger: " + message);
	}

}

3)类似的再创建继承了基类 AbstractLogger 的两个处理器,FileLogger ErrorLogger

 FileLogger.java

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.chainOfResponsibilityPattern;

public class FileLogger extends AbstractLogger {

	public FileLogger(int level){
		this.level = level;
	}
	
	@Override
	protected void write(String message) {
		System.out.println("File::Logger: " + message);
	}

}

ErrorLogger.java

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.chainOfResponsibilityPattern;

public class ErrorLogger extends AbstractLogger {

	public ErrorLogger(int level){
		this.level = level;
	}
	
	@Override
	protected void write(String message) {
		System.out.println("Error Console::Logger: " + message);
	}

}

4)客户端构建一个处理器的责任链请求示例 ChainPatternDemo

创建不同类型的记录器,赋予它们不同的错误级别;

并在每个记录器中设置下一个记录器,每个记录器中的下一个记录器代表的是链的一部分。

 ChainPatternDemo.java

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.chainOfResponsibilityPattern;

/**
 * 客户端构建一个处理器的责任链
 * @Date 2022年10月5日
 * @author zhaoYanFei
 *
 */
public class ChainPatternDemo {

	private static AbstractLogger getChainOfLoggers() {
		//先实例化不同级别的日志对象
		AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
		AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
		AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
		//error 级别最高,初始error日志处理器处理,如果不能处理,丢给下一个处理器
		errorLogger.setNextLogger(fileLogger);
		//以此类推,上一个FileLogger 不能处理的传递给ConsoleLogger对象处理
		fileLogger.setNextLogger(consoleLogger);
		return errorLogger;
	}
	
	public static void main(String[] args) {
		//构建责任链
		AbstractLogger chainOfLoggers = getChainOfLoggers();
		
		chainOfLoggers.logMessage(AbstractLogger.INFO, "This is an info information.");
		chainOfLoggers.logMessage(AbstractLogger.DEBUG, "This is an debug information.");
		chainOfLoggers.logMessage(AbstractLogger.ERROR, "This is an error information.");
	}
}

 5)查看运行结果

 4、责任链的优缺点

4.1、优点

1、降低耦合度。它将请求的发送者和接收者解耦。

2、简化了对象。使得对象不需要知道链的结构。

3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。

4、增加新的请求处理类很方便。

4.2、缺点

1、不能保证请求一定被接收。

2、系统性能将受到一定影响,而且可能会造成循环调用。

3、运行期特征不易观察,排除问题不太友好。

5、责任链模式的应用场景 

1、事件处理器,例如 js 中的事件冒泡;大部分图形用户界面框架使用责任链模式来处理事件。

2、日志处理器

3、JAVA WEB 中 servlet ,在 Java 中,javax.servlet.Filter 被用来过滤请求或者响应。 doFilter 方法把过滤器链作为一个参数接收,它能够传递请求。

4、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器等等。

6、结语

这一章节主要给大家分享了责任链模式的定义以及它的应用场景,下一节给大家分享命令模式。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、责任链模式的概念
    • 1.1、百度百科对责任链的定义
      • 1.2、责任链模式
      • 2、责任链模式的作用
      • 3、实现
        • 3.1、责任链模式的通用类图,如下图 1-1:
          • 3.2、代码实现案例
          •  4、责任链的优缺点
            • 4.1、优点
              • 4.2、缺点
              • 5、责任链模式的应用场景 
              • 6、结语
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档