JAVA设计模式——责任链模式

责任链模式是一种行为型设计模式。责任链模式的思想是:为请求创建了一个接收者对象的链,如果一个接收者对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推

责任链模式涉及到2个角色:

  • 抽象处理者(Handler):定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。
  • 具体处理者(Concrete Handler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。

结构图:
这里写图片描述

具体代码实现:

// 抽象处理者
public abstract class Handler {
    protected Handler successor; // 责任链上下一个处理者的引用

    public Handler getSuccessor() {
        return successor;
    }

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void handle(); // 处理请求

}

// 具体处理者
public class HandlerA extends Handler {
    @Override
    public void handle() {
        Handler s = getSuccessor();
        if (s == null) {
            // 如果没有下一个处理者,则自己处理
            System.out.println("Handle!!");
        } else {
            // 如果有下一个处理者,则交由下一个处理者处理
            System.out.println("Pass...");
            s.handle();
        }
    }
}

// 客户
public class Client {
    public void method() {
        Handler h1 = new HandlerA();
        Handler h2 = new HandlerA();
        Handler h3 = new HandlerA();
        Handler h4 = new HandlerA();
        h1.setSuccessor(h2);
        h2.setSuccessor(h3);
        h3.setSuccessor(h4);
        h1.handle();
    }
}

// 测试
class ResponsibilityTest {
    public static void main(String[] args) {
        Client client = new Client();
        client.method();
    }
}

运行结果:

Pass…
Pass…
Pass…
Handle!!

可以看到,责任链模式并不创建出责任链。责任链的创建必须有系统的其它部分完成(不一定是客户)。

责任链模式降低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求。一个链可以是一条线,一个环,一个树,也可以是现有树的一部分。链的拓扑结构可以是单连通的或多连通的,责任链模式并不指定责任链的拓扑结构,但是责任链模式要求在同一个时间里,命令只可以被传给一个下家(或被处理掉);而不可以传给多于一个下家。

责任链模式的缺点主要是性能问题。一方面,如果链很长,而真正处理请求的对象在链条末端,那么处理这个请求的时间就比较长;另一方面,链条中的每个节点都是一个对象,而有时候这当中很多对象在业务场景中可能根本用不上,这就造成了内存空间的浪费


下面再提供一个例子,用责任链模式实现不同级别日志的输出。

// 日志级别枚举
public enum LogLevel {
    INFO(1), WARNING(2), ERROR(3);

    public int index;

    LogLevel(int index) {
        this.index = index;
    }
}

// 抽象日志记录器
public abstract class Logger {
    protected Logger nextLogger; // 责任链中下一个日志记录器的引用
    protected LogLevel level; // 当前日志记录器的级别

    public Logger getNextLogger() {
        return nextLogger;
    }

    public void setNextLogger(Logger nextLogger) {
        this.nextLogger = nextLogger;
    }

    // 写日志
    public void log(LogLevel level, String msg) {
        if (this.level.index < level.index) {
            // 如果当前记录器级别过低,则交由下一个记录器处理
            nextLogger.log(level, msg); 
        } else {
            // 如果当前记录器级别高于要记录的级别,则直接处理
            write(msg);
        }
    }

    // 输出日志信息到控制台,根据日志级别不同显示的格式也不同
    protected abstract void write(String msg);
}

// INFO级别的日志记录器
public class InfoLogger extends Logger {
    public InfoLogger() {
        this.level = LogLevel.INFO;
    }

    @Override
    protected void write(String msg) {
        System.out.printf("[INFO] %s\n", msg);
    }
}

// WARNING级别的日志记录器
pulbic class WarningLogger extends Logger {
    public WarningLogger() {
        this.level = LogLevel.WARNING;
    }

    @Override
    protected void write(String msg) {
        System.out.printf("[WARNING] %s\n", msg);
    }
}

// ERROR级别的日志记录器
public class ErrorLogger extends Logger {
    public ErrorLogger() {
        this.level = LogLevel.ERROR;
    }

    @Override
    protected void write(String msg) {
        System.out.printf("[ERROR] %s\n", msg);
    }
}

// 客户
public class Client {
    // 模拟一个写日志的方法
    public void method(LogLevel level, String msg) {
        Logger info = new InfoLogger();
        Logger warn = new WarningLogger();
        Logger error = new ErrorLogger();

        // 构造责任链
        info.setNextLogger(warn);
        warn.setNextLogger(error);

        // 向责任链中不同的节点发送请求,检验效果
        info.log(level, msg);
        warn.log(level, msg);
    }
}

// 测试
class LoggerTest {
    public static void main(String[] args) {
        Client client = new Client();
        client.method(LogLevel.ERROR, "An error occurred!!");
        System.out.println("==========");
        client.method(LogLevel.INFO, "There is an information");
    }
}

运行结果:

[ERROR] An error occurred!!
[ERROR] An error occurred!!
==========
[INFO] There is an information.
[WARNING] There is an information.

结构图:
这里写图片描述


最后总结一下责任链模式的应用场景:

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

在JAVA WEB中,责任链模式随处可见,典型的应用是各种的过滤器(Filter)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值