设计模式-责任链模式

作者持续关注 WPS二次开发专题系列,持续为大家带来更多有价值的WPS开发技术细节,如果能够帮助到您,请帮忙来个一键三连,更多问题请联系我(QQ:250325397)

目录

定义

特点

使用场景

优缺点

[(1) 优点](#(1) 优点)

[(2) 缺点](#(2) 缺点)

模式结构

具体实现

实际应用


定义

责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

特点

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

使用场景

    • 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
    • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
    • 可动态指定一组对象处理请求。

优缺点

(1) 优点
    • 降低耦合度。它将请求的发送者和接收者解耦。
    • 简化了对象。使得对象不需要知道链的结构。
    • 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
    • 增加新的请求处理类很方便。
(2) 缺点
    • 不能保证请求一定被接收。
    • 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
    • 可能不容易观察运行时的特征,有碍于除错。

模式结构

    • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
    • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
    • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理;理解责任链模式应当理解其模式,而不是其具体实现。责任链模式的独到之处是将其节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动起来。

具体实现

抽象类

java 复制代码
/**
 * 日志接口
 */
public interface ILogger {
    int INFO = 1;
    int DEBUG = 2;
    int ERROR = 3;

    /**
     * 记录日志
     * @param level 日志级别
     * @param msg 日志内容
     */
    void doLogger(int level, String msg, LoggerChain chain);
}

/**
 * 控制台打印日志
 */
public class ConsoleLogger implements ILogger {
    @Override
    public void doLogger(int level, String msg, LoggerChain chain) {
        //处理当前日志打印
        System.out.println("Console Logger::[" + level + "] " + msg);
        //继续向下处理
        chain.doLogger(level, msg, chain);
    }
}

/**
 * file级别的日志
 */
public class FileLogger implements ILogger {
    @Override
    public void doLogger(int level, String msg, LoggerChain chain) {
        //处理当前日志打印,写入到文件中
        System.out.println("Filter Logger::[" + level + "] " + msg);
        //继续向下处理
        chain.doLogger(level, msg, chain);
    }
}

/**
 * 日志校验器
 */
public class ValidateLogger implements ILogger {
    @Override
    public void doLogger(int level, String msg, LoggerChain chain) {
        msg = msg.replace("sdcard", "xxx");
        chain.doLogger(level, msg, chain);
    }
}

责任链类

java 复制代码
/**
 * 日志处理器链
 */
public class LoggerChain implements ILogger {
    //日志处理器列表
    private List<ILogger> loggerList = new ArrayList<>();

    //当前处理的索引,从0开始
    private int index;

    /**
     * 添加日志处理器
     */
    public LoggerChain addLogger(ILogger logger) {
        loggerList.add(logger);
        return this;
    }

    @Override
    public void doLogger(int level, String msg, LoggerChain chain) {
        if (index == loggerList.size()) {
            //处理到最后,则返回
            return;
        }
        //继续使用下一个日志处理器处理
        ILogger logger = loggerList.get(index);
        index ++;
        logger.doLogger(level, msg, chain);
    }
}

具体使用

java 复制代码
public class App {
    public static void main(String[] args) {

        LoggerChain logger = new LoggerChain();
        logger.addLogger(new ConsoleLogger())
        //可添加日志敏感内容过滤器或者日志加密器
                .addLogger(new ValidateLogger())
                .addLogger(new FileLogger());
        logger.doLogger(ILogger.INFO, "This is a test log msg, file path:/sdcard/test/test.pdf", logger);
    }
}

实际应用

  1. Spring中的拦截器,Servlet中的过滤器
  2. Android中View的touch事件冒泡
相关推荐
小萌新上大分20 小时前
java线程通信 生产者消费者,synchronized,,ReentrantLock,Condition(笔记备份)
java·多线程·lock·java线程间通信的方式·reentrantlock使用·生产者消费者问题java·java多线程与高并发
それども20 小时前
Spring Bean 的name可以相同吗
java·后端·spring
墨雪不会编程20 小时前
C++ string 详解:STL 字符串容器的使用技巧
java·开发语言·c++
Lucky GGBond20 小时前
实践开发:老系统新增字段我是如何用枚举优雅兼容历史数据的
java
悲喜自渡72120 小时前
Python 编程(gem5 )
java·linux·开发语言
xing-xing20 小时前
JVM 内存、直接内存、系统内存、本地内存、物理内存总结
java·jvm
yangpipi-20 小时前
《C++并发编程实战》第5章 C++内存模型和原子操作
android·java·c++
qq_124987075321 小时前
基于微信小程序的电子元器件商城(源码+论文+部署+安装)
java·spring boot·spring·微信小程序·小程序·毕业设计
吃喝不愁霸王餐APP开发者21 小时前
基于Spring Cloud Gateway实现对外卖API请求的统一鉴权与流量染色
java·开发语言
a努力。21 小时前
美团Java面试被问:Redis集群模式的工作原理
java·redis·后端·面试