设计模式-责任链模式(Chain of Responsibility)

设计模式-责任链模式(Chain of Responsibility)

    • 一、责任链模式概述
      • 1.1 什么是责任链模式
      • 1.2 简单实现责任链模式
      • 1.3 使用责任链模式的注意事项
    • 二、责任链模式的用途
    • 三、责任链模式实现方式
      • 3.1 基于接口实现责任链模式
      • 3.2 基于抽象类实现责任链模式
      • 3.3 基于匿名内部类实现责任链模式
      • 3.4 基于Lambda表达式实现责任链模式

一、责任链模式概述

1.1 什么是责任链模式

责任链模式是一种面向对象设计模式,该模式中包含了一系列处理对象和命令对象。每个处理对象都有能力决定自己可以处理哪些命令对象,如果遇到无法处理的命令对象,它会将请求传递给下一个处理对象。这种模式的核心在于避免请求发送者与接收者之间的紧密耦合,让多个对象都有可能接收请求,并将这些对象连接成一条链,沿着这条链传递请求,直到有对象处理它为止。

以公司员工请假为例,员工的请假请求可能有多个领导可以批准,但每个领导的批准权限不同。员工需要根据自己要请假的天数去找对应的领导签名。这就是责任链模式的一个生动实例。其实现过程就如同“击鼓传花”游戏,每个参与者都有机会处理事件,但如果无法处理则继续传给下一个人。

在开发中,责任链模式常用于处理复杂数据处理和校验的场景。通过使用责任链模式,可以将一个请求的处理过程分解为一系列的处理对象,使得代码更加清晰、灵活和易于维护。

1.2 简单实现责任链模式

首先,我们定义一个抽象的处理类(Handler):

public abstract class Handler {
    protected Handler nextHandler;

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handleRequest(String request);
}

然后,我们创建具体的处理类(ConcreteHandler),它们继承自抽象的处理类,并实现了handleRequest方法:

public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.equals("A")) {
            System.out.println("ConcreteHandlerA处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

public class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.equals("B")) {
            System.out.println("ConcreteHandlerB处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

然后,我们创建具体的处理类(ConcreteHandler),它们继承自抽象的处理类,并实现了handleRequest方法:

public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.equals("A")) {
            System.out.println("ConcreteHandlerA处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

public class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.equals("B")) {
            System.out.println("ConcreteHandlerB处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

最后,我们在客户端代码中创建处理器对象,并将它们连接起来:

public class Client {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();

        handlerA.setNextHandler(handlerB);

        handlerA.handleRequest("A"); // 输出:ConcreteHandlerA处理了请求:A
        handlerA.handleRequest("B"); // 输出:ConcreteHandlerB处理了请求:B
        handlerA.handleRequest("C"); // 输出:没有处理器可以处理该请求:C
    }
}

这样,我们就实现了一个简单的责任链模式。当客户端发送一个请求时,它会沿着责任链传递,直到找到一个可以处理该请求的处理器。

1.3 使用责任链模式的注意事项

  • 1、存在循环调用的风险。在实现责任链模式时,可能存在节点之间的循环调用,从而形成死循环。这种循环调用的风险通常出现在两种情况下:一是责任链节点自身会对请求进行多次处理;二是责任链节点之间相互调用。为了避免这种情况,需要对责任链节点的处理逻辑进行严格的控制和规范,确保节点的处理逻辑只能一次性地对请求进行处理,并且不会出现相互调用的情况。另外,可以通过设置最大处理次数或者设置超时时间等机制来防止出现死循环,从而避免对系统的影响。

  • 2、确定责任链的顶端和底端。在实现责任链模式时,需要确定责任链的顶端和底端,以确保请求能够被正确地传递和处理。

  • 3、避免请求发送者与接收者之间的紧密耦合关系。在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,这样可以降低系统的耦合度。

  • 4、注意性能问题。由于每个处理器都需要处理请求和传递请求,因此使用责任链模式可能会导致系统性能下降。为了解决这个问题,可以考虑使用异步处理等方式来提高系统的性能。

二、责任链模式的用途

责任链模式主要用于处理那些需要经过多个处理步骤或处理者才能完成的请求。其主要应用场景包括:

  • 1、过滤器模式:例如在Java Web应用中,过滤器链用于对HTTP请求和响应进行处理。每个过滤器负责处理特定的任务,然后将请求传递给下一个过滤器。这种场景下,责任链模式可以有效地解耦每个过滤器的处理逻辑。

  • 2、事件处理模式:在图形用户界面编程中,事件处理通常采用责任链模式。例如在一个按钮上,可能有多个监听器(如点击、鼠标移动等),每个监听器负责处理一种特定的事件。当事件发生时,会沿着监听器链进行传递,直到有监听器处理该事件为止。

  • 3、工作流引擎:在企业级应用中,工作流引擎通常使用责任链模式来处理复杂的业务流程。每个处理节点负责处理流程中的特定步骤,然后将工作项传递给下一个处理节点。

  • 4、权限设计:在权限设计中,可以使用责任链模式来实现权限验证。例如,一个用户可能需要经过多个角色的权限验证,每个角色负责验证一部分权限。这样既可以实现权限验证的逻辑分离,又可以提高系统的灵活性和扩展性。

三、责任链模式实现方式

3.1 基于接口实现责任链模式

首先,我们需要定义一个处理请求的接口,然后创建具体的处理器类实现该接口。最后,在客户端代码中,我们将处理器对象链接在一起,形成一个责任链。

以下是一个简单的Java实现:

定义处理请求的接口:

public interface RequestHandler {
    void setNextHandler(RequestHandler nextHandler);
    void handleRequest(String request);
}

创建具体的处理器类实现该接口:

public class ConcreteHandlerA implements RequestHandler {
    private RequestHandler nextHandler;

    @Override
    public void setNextHandler(RequestHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    @Override
    public void handleRequest(String request) {
        if (request.startsWith("A")) {
            System.out.println("ConcreteHandlerA处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

public class ConcreteHandlerB implements RequestHandler {
    private RequestHandler nextHandler;

    @Override
    public void setNextHandler(RequestHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    @Override
    public void handleRequest(String request) {
        if (request.startsWith("B")) {
            System.out.println("ConcreteHandlerB处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

在客户端代码中,将处理器对象链接在一起,形成一个责任链:

public class Client {
    public static void main(String[] args) {
        RequestHandler handlerA = new ConcreteHandlerA();
        RequestHandler handlerB = new ConcreteHandlerB();

        handlerA.setNextHandler(handlerB);

        handlerA.handleRequest("A1");
        handlerA.handleRequest("B1");
        handlerA.handleRequest("C1");
    }
}

运行客户端代码,输出结果如下:

ConcreteHandlerA处理了请求:A1
ConcreteHandlerB处理了请求:B1
没有处理器可以处理该请求:C1

3.2 基于抽象类实现责任链模式

要实现基于抽象类的责任链模式,首先需要创建一个抽象类,然后创建具体的处理器类继承自抽象类。最后在客户端代码中,将处理器对象链接在一起,形成一个责任链。以下是一个简单的示例:

创建一个抽象类Handler:

public abstract class Handler {
    protected Handler nextHandler;

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handleRequest(String request);
}

创建具体的处理器类ConcreteHandlerA和ConcreteHandlerB,分别继承自Handler:

public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.equals("A")) {
            System.out.println("ConcreteHandlerA处理了请求:" + request);
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("没有处理器可以处理该请求:" + request);
            }
        }
    }
}

public class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.equals("B")) {
            System.out.println("ConcreteHandlerB处理了请求:" + request);
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("没有处理器可以处理该请求:" + request);
            }
        }
    }
}

在客户端代码中,将处理器对象链接在一起,形成一个责任链:

public class Client {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();

        handlerA.setNextHandler(handlerB);

        handlerA.handleRequest("A");
        handlerA.handleRequest("B");
        handlerA.handleRequest("C");
    }
}

运行客户端代码,输出结果如下:

ConcreteHandlerA处理了请求:A
ConcreteHandlerB处理了请求:B
没有处理器可以处理该请求:C

3.3 基于匿名内部类实现责任链模式

public interface Handler {
    void setNextHandler(Handler nextHandler);
    void handleRequest(String request);
}

public class ConcreteHandlerA implements Handler {
    private Handler nextHandler;

    @Override
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    @Override
    public void handleRequest(String request) {
        if ("A".equals(request)) {
            System.out.println("ConcreteHandlerA处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

public class ConcreteHandlerB implements Handler {
    private Handler nextHandler;

    @Override
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    @Override
    public void handleRequest(String request) {
        if ("B".equals(request)) {
            System.out.println("ConcreteHandlerB处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

public class Client {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();

        handlerA.setNextHandler(handlerB);

        handlerA.handleRequest("A");
        handlerA.handleRequest("B");
        handlerA.handleRequest("C");
    }
}

3.4 基于Lambda表达式实现责任链模式

责任链模式是一种行为设计模式,它允许多个对象处理一个请求,从而避免了请求的发送者和接收者之间的耦合关系。在Java中,我们可以使用Lambda表达式和接口来实现责任链模式。

首先,我们需要定义一个处理器接口,该接口包含一个处理方法:

public interface Handler {
    void handleRequest(String request);
}

接下来,我们可以创建具体的处理器类,实现这个接口:

public class ConcreteHandlerA implements Handler {
    private Handler nextHandler;

    @Override
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    @Override
    public void handleRequest(String request) {
        if (request.equals("A")) {
            System.out.println("ConcreteHandlerA处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

public class ConcreteHandlerB implements Handler {
    private Handler nextHandler;

    @Override
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    @Override
    public void handleRequest(String request) {
        if (request.equals("B")) {
            System.out.println("ConcreteHandlerB处理了请求:" + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理器可以处理该请求:" + request);
        }
    }
}

最后,我们可以使用Lambda表达式来创建处理器对象,并设置责任链:

public class Main {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();

        handlerA.setNextHandler(handlerB);

        handlerA.handleRequest("A");
        handlerA.handleRequest("B");
        handlerA.handleRequest("C");
    }
}

运行上述代码,输出结果如下:

ConcreteHandlerA处理了请求:A
ConcreteHandlerB处理了请求:B
没有处理器可以处理该请求:C

你可能感兴趣的:(#,设计模式,设计模式,责任链模式)