设计模式-责任链模式

作者持续关注 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事件冒泡
相关推荐
魔道不误砍柴功36 分钟前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_23436 分钟前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨39 分钟前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
测开小菜鸟2 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
P.H. Infinity3 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天3 小时前
java的threadlocal为何内存泄漏
java
caridle3 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^3 小时前
数据库连接池的创建
java·开发语言·数据库
苹果醋34 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
秋の花4 小时前
【JAVA基础】Java集合基础
java·开发语言·windows