墨风如雪博客

  • 源码小店
  • 导航站
  • 登录
  • java
  • 资源分享
让AI使用变得如此简单
  1. 首页
  2. java
  3. 设计模式
  4. 正文

设计模式:责任链设计模式

2023年 6月 14日 121点热度 0人点赞 0条评论

一、概述

责任链设计模式是一种行为型设计模式,它将请求的发送者和接收者解耦,将多个处理对象连成一条责任链,依次处理请求,直到请求被处理或者到达责任链的末尾。该模式常用于日志记录、权限验证、请求过滤等场景。

1.1 定义

责任链模式定义了一种处理请求的方式,它让多个处理对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。

1.2 应用场景

责任链模式适用于以下场景:

  • 处理对象不确定,需要动态指定处理对象。
  • 多个处理对象可以处理同一个请求,但处理对象的顺序可能不同。
  • 处理对象的数量和顺序可以动态变化。

1.3 优缺点

责任链模式的优点包括:

  • 降低了对象之间的耦合度,提高了代码的灵活性和可扩展性。
  • 可以动态地增加或删除处理对象,方便了系统的维护和升级。
  • 可以对请求进行灵活的处理,提高了系统的可用性和性能。

责任链模式的缺点包括:

  • 可能存在请求不能被处理的情况,需要在责任链的末端添加默认处理对象。
  • 系统性能受到责任链长度和处理对象数量的影响。

二、角色介绍

责任链模式包含以下角色:

2.1 抽象处理者(Handler)

抽象处理者定义了一个处理请求的接口,并保存下一个处理对象的引用。它可以是抽象类或接口。

public abstract class Handler {
    protected Handler nextHandler;

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

    public abstract void handleRequest(Request request);
}

2.2 具体处理者(ConcreteHandler)

具体处理者实现了抽象处理者的接口,并处理它所负责的请求。如果不能处理该请求,则将请求传递给下一个处理对象。

public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_A) {
            // 处理请求
        } else {
            // 无法处理该请求,将请求传递给下一个处理对象
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                // 如果没有下一个处理对象,则输出日志
                System.out.println("No handler available for request.");
            }
        }
    }
}

2.3 客户端(Client)

客户端创建请求对象,并将其发送给第一个处理对象。客户端可以根据需要自定义处理对象的顺序,也可以动态地增加或删除处理对象。

public class Client {
    public static void main(String[] args) {
        // 创建请求对象
        Request request = new Request(RequestType.TYPE_A, "Request A");

        // 创建处理对象
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();

        // 构建责任链
        handlerA.setNextHandler(handlerB);
        handlerB.setNextHandler(handlerC);

        // 发送请求
        handlerA.handleRequest(request);
    }
}

三、实现步骤

实现责任链模式的步骤如下:

3.1 定义抽象处理者接口

首先,我们需要定义一个抽象处理者接口,该接口包含一个处理请求的方法和一个设置下一个处理对象的方法。

public abstract class Handler {
    protected Handler nextHandler;

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

    public abstract void handleRequest(Request request);
}

3.2 定义具体处理者类

接着,我们需要定义具体的处理者类,这些类实现了抽象处理者接口,并根据具体的业务需求处理请求。如果当前处理对象无法处理该请求,则将请求传递给下一个处理对象。

public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_A) {
            // 处理请求
        } else {
            // 无法处理该请求,将请求传递给下一个处理对象
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                // 如果没有下一个处理对象,则输出日志
                System.out.println("No handler available for request.");
            }
        }
    }
}

public class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(Requestrequest) {
        if (request.getType() == RequestType.TYPE_B) {
            // 处理请求
        } else {
            // 无法处理该请求,将请求传递给下一个处理对象
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                // 如果没有下一个处理对象,则输出日志
                System.out.println("No handler available for request.");
            }
        }
    }
}

public class ConcreteHandlerC extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_C) {
            // 处理请求
        } else {
            // 无法处理该请求,将请求传递给下一个处理对象
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                // 如果没有下一个处理对象,则输出日志
                System.out.println("No handler available for request.");
            }
        }
    }
}

3.3 构建责任链

接下来,我们需要将具体处理者对象连成一条责任链,以便依次处理请求。可以在客户端中手动设置处理对象的顺序,也可以使用链表、静态链表或线程池方式动态构建责任链。

Handler链的构建方式可以有多种,下面分别介绍链表、静态链表和线程池方式。

链表方式构建责任链:

Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();

handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);

静态链表方式构建责任链:

Handler[] handlers = new Handler[] {
    new ConcreteHandlerA(),
    new ConcreteHandlerB(),
    new ConcreteHandlerC()
};

for (int i = 0; i < handlers.length - 1; i++) {
    handlers[i].setNextHandler(handlers[i + 1]);
}

线程池方式构建责任链:

Executor executor = Executors.newFixedThreadPool(3);

Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();

handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);

executor.execute(handlerA);

3.4 客户端调用

最后,我们需要创建一个请求对象,并将其发送给第一个处理对象。客户端可以根据需要自定义处理对象的顺序,也可以动态地增加或删除处理对象。

public class Client {
    public static void main(String[] args) {
        // 创建请求对象
        Request requestA = new Request(RequestType.TYPE_A, "Request A");
        Request requestB = new Request(RequestType.TYPE_B, "Request B");

        // 创建处理对象
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();

        // 构建责任链
        handlerA.setNextHandler(handlerB);
        handlerB.setNextHandler(handlerC);

        // 发送请求
        handlerA.handleRequest(requestA);
        handlerA.handleRequest(requestB);
    }
}

四、代码示例

下面是一个完整的责任链模式的代码示例:

4.1 抽象处理者接口

public abstract class Handler {
    protected Handler nextHandler;

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

    public abstract void handleRequest(Request request);
}

4.2 具体处理者类

public class ConcreteHandlerA extends Handler {
     @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_A) {
            System.out.println("Handled by ConcreteHandlerA: " + request.getContent());
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available for request.");
            }
        }
    }
}

public class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_B) {
            System.out.println("Handled by ConcreteHandlerB: " + request.getContent());
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available for request.");
            }
        }
    }
}

public class ConcreteHandlerC extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_C) {
            System.out.println("Handled by ConcreteHandlerC: " + request.getContent());
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available for request.");
            }
        }
    }
}

4.3 构建责任链

Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
HandlerC = new ConcreteHandlerC();

handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);

4.4 客户端调用

public class Client {
    public static void main(String[] args) {
        // 创建请求对象
        Request requestA = new Request(RequestType.TYPE_A, "Request A");
        Request requestB = new Request(RequestType.TYPE_B, "Request B");
        Request requestC = new Request(RequestType.TYPE_C, "Request C");
        Request requestD = new Request(RequestType.TYPE_D, "Request D");

        // 创建处理对象
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();

        // 构建责任链
        handlerA.setNextHandler(handlerB);
        handlerB.setNextHandler(handlerC);

        // 发送请求
        handlerA.handleRequest(requestA);
        handlerA.handleRequest(requestB);
        handlerA.handleRequest(requestC);
        handlerA.handleRequest(requestD);
    }
}

输出结果如下:

Handled by ConcreteHandlerA: Request A
Handled by ConcreteHandlerB: Request B
Handled by ConcreteHandlerC: Request C
No handler available for request.

五、优化方案

5.1 链表方式构建责任链

在实现责任链模式时,我们可以使用链表方式构建责任链,以便动态添加或删除处理对象。具体方式是将处理对象保存在链表中,并在处理请求时依次调用链表中的处理对象。

public class HandlerChain {
    private List<Handler> handlers = new ArrayList<>();

    public void addHandler(Handler handler) {
        handlers.add(handler);
    }

    public void handleRequest(Request request) {
        for (Handler handler : handlers) {
            if (handler.handleRequest(request)) {
                break;
            }
        }
    }
}

在上述代码中,我们创建了一个HandlerChain类,它包含一个处理对象列表handlers,可以动态添加或删除处理对象。handleRequest方法遍历handlers列表中的处理对象,并调用它们的handleRequest方法,如果其中一个处理对象能够处理该请求,则返回true,表示请求已被处理,否则继续遍历直到所有的处理对象都无法处理该请求。

5.2 静态链表方式构建责任链

我们也可以使用静态链表方式构建责任链,这种方式通过在处理对象中保存下一个处理对象的引用,以便在处理请求时依次调用链表中的处理对象。

public abstract classHandler {
    protected Handler nextHandler;

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

    public abstract boolean handleRequest(Request request);
}

public class ConcreteHandlerA extends Handler {
    public ConcreteHandlerA(Handler nextHandler) {
        super(nextHandler);
    }

    @Override
    public boolean handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_A) {
            System.out.println("Handled by ConcreteHandlerA: " + request.getContent());
            return true;
        } else {
            if (nextHandler != null) {
                return nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available for request.");
                return false;
            }
        }
    }
}

public class ConcreteHandlerB extends Handler {
    public ConcreteHandlerB(Handler nextHandler) {
        super(nextHandler);
    }

    @Override
    public boolean handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_B) {
            System.out.println("Handled by ConcreteHandlerB: " + request.getContent());
            return true;
        } else {
            if (nextHandler != null) {
                return nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available for request.");
                return false;
            }
        }
    }
}

public class ConcreteHandlerC extends Handler {
    public ConcreteHandlerC(Handler nextHandler) {
        super(nextHandler);
   }

    @Override
    public boolean handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_C) {
            System.out.println("Handled by ConcreteHandlerC: " + request.getContent());
            return true;
        } else {
            if (nextHandler != null) {
                return nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available for request.");
                return false;
            }
        }
    }
}

在上述代码中,我们创建了一个Handler抽象类,它包含一个nextHandler属性,用于保存下一个处理对象的引用。ConcreteHandlerA、ConcreteHandlerB、ConcreteHandlerC类继承自Handler类,并在构造函数中初始化nextHandler属性。handleRequest方法首先判断是否能够处理该请求,如果能够处理,则处理请求并返回true,否则调用下一个处理对象的handleRequest方法处理该请求,如果下一个处理对象为null,则表示没有处理对象能够处理该请求,返回false。

5.3 链式调用方式构建责任链

我们还可以使用链式调用方式构建责任链,这种方式通过在处理对象中返回自身引用,以便在处理请求时依次调用链表中的处理对象。

责任链模式是一种行为型设计模式,它允许多个对象按照一定的顺序依次处理同一个请求,直到其中一个对象处理该请求或者所有对象都无法处理该请求为止。该模式有助于降低请求发送者与接收者之间的耦合度,增强系统的灵活性和可扩展性。

在责任链模式中,我们通常需要实现以下几个角色:

  1. 抽象处理者(Handler):定义处理请求的接口,并保存下一个处理者的引用;
  2. 具体处理者(ConcreteHandler):实现抽象处理者定义的处理请求接口,如果自己能够处理该请求,则处理请求,否则将请求传递给下一个处理者;
  3. 请求(Request):包含需要处理的信息;
  4. 客户端(Client):创建请求对象,并将其发送给第一个处理者。

下面是一个简单的责任链模式的实现例子:

public abstract class Handler {
    protected Handler nextHandler;

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

    public abstract void handleRequest(Request request);
}

在上述代码中,我们定义了一个Handler抽象类,它包含一个nextHandler属性,用于保存下一个处理对象的引用。setNextHandler方法用于设置下一个处理对象。handleRequest方法定义了处理请求的接口,具体的处理逻辑由子类实现。

定义请求类

public class Request {
    private RequestType type;
    private String content;

    public Request(RequestType type, String content) {
        this.type = type;
        this.content = content;
    }

    public RequestType getType() {
        return type;
    }

    public String getContent() {
        return content;
    }
}

在上述代码中,我们定义了一个Request类,它包含了需要处理的信息,包括请求类型和请求内容。

定义具体处理者类

public class HandlerA extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_A) {
            System.out.println("Handled by HandlerA: " + request.getContent());
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available for request.");
            }
        }
    }
}

public class HandlerB extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_B) {
            System.out.println("Handled by HandlerB: " + request.getContent());
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available for request.");
            }
        }
    }
}

public class HandlerC extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_C) {
            System.out.println("Handled by HandlerC: " + request.getContent());
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.println("No handler available for request.");
            }
        }
    }
}

在上述代码中,我们创建了三个具体处理者类HandlerA、HandlerB、HandlerC,它们分别处理请求类型为TYPE_A、TYPE_B、TYPE_C的请求。如果自己能够处理该请求,则处理请求;否则将请求传递给下一个处理者处理。

构建责任链

Handler handlerA = new HandlerA();
Handler handlerB = new HandlerB();
Handler handlerC = new HandlerC();

handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);

在上述代码中,我们创建了三个处理者对象handlerA、handlerB、handlerC,并按照顺序构建了责任链,将它们连接起来。

客户端调用

public class Client {
    public static void main(String[] args) {
        // 创建请求对象
        Request requestA = new Request(RequestType.TYPE_A, "Request A");
        Request requestB = new Request(RequestType.TYPE_B, "Request B");
        Request requestC = new Request(RequestType.TYPE_C, "Request C");
        Request requestD = new Request(RequestType.TYPE_D, "Request D");

        // 创建处理对象
        Handler handlerA = new HandlerA();
        Handler handlerB = new HandlerB();
        Handler handlerC = new HandlerC();

        // 构建责任链
        handlerA.setNextHandler(handlerB);
        handlerB.setNextHandler(handlerC);

        // 发送请求
        handlerA.handleRequest(requestA);
        handlerA.handleRequest(requestB);
        handlerA.handleRequest(requestC);
        handlerA.handleRequest(requestD);
    }
}

在上述代码中,我们创建了四个请求对象requestA、requestB、requestC、requestD,并创建了三个处理对象handlerA、handlerB、handlerC。然后构建了责任链,并将请求发送给第一个处理对象handlerA。输出结果如下:

Handled by HandlerA: Request A
Handled by HandlerB: Request B
Handled by HandlerC: Request C
No handler available for request.

六、适用场景

责任链模式适用于以下场景:

  1. 处理一个请求的对象集合可以动态配置;
  2. 需要避免请求发送者和接收者之间的耦合关系,或者希望动态指定请求处理者的情况;
  3. 多个对象可以处理同一请求,但是具体哪个对象处理该请求在运行时才能确定;
  4. 在不明确指定接收者的情况下,向多个对象中的一个或几个对象发出请求,而不必显式指定接收者。

七、优缺点

7.1 优点

  1. 降低系统的耦合度:请求发送者和接收者之间的耦合度降低,因为发送者不需要知道请求的处理细节,而只需要知道一个处理请求的对象即可;
  2. 增强系统的灵活性和可扩展性:可以动态地增加或删除处理者,而不需要修改原有的代码;
  3. 简化对象之间的交互:责任链模式可以通过链式调用方式简化对象之间的交互,使得代码更加简洁易懂。

7.2 缺点

  1. 对请求的处理顺序敏感:如果处理者之间的处理顺序发生变化,可能会导致请求的处理结果不正确,因此需要仔细设计责任链的结构;
  2. 可能会导致请求得不到处理:如果责任链没有正确地构建,或者没有设置好处理对象的顺序,可能会导致某些请求得不到处理;
  3. 可能会影响系统性能:责任链模式可能会导致请求需要遍历整个责任链才能得到处理,而且在链较长的情况下可能会影响系统的性能。
本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: java spring 教程 设计模式 详解 责任链设计模式
最后更新:2023年 5月 27日

墨风如雪

一个热爱生活,热爱分享的程序员

打赏 点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

墨风如雪

一个热爱生活,热爱分享的程序员

最新 热点 随机
最新 热点 随机
告别机械感!OpenAudio S1让AI声音活起来 Sora触手可及!微软必应AI视频生成器,全民创作时代来临? 阿里WebAgent开源:引领自主搜索新纪元 重磅炸弹!字节跳动开源BAGEL:70亿参数,统一多模态理解与生成,AI“全能王”诞生记! 小米MiMo-VL:7B参数,怎么就成了多模态界的“越级打怪王”? 炸裂!DeepSeek 8B 量化版降临:告别显存焦虑,你的 3080 Ti 也能玩转顶级大模型了!
炸裂!微软这门免费AI Agent新手课,GitHub近2万星,简直是宝藏!ComfyUI“打通任督二脉”:直接调用Veo2、GPT-4o等65大模型!一键串联你的AI工作流AI圈炸锅了!Mistral Medium 3:性能 SOTA,成本打骨折,企业玩家的新宠?字节终于开源“扣子”同款引擎了!FlowGram:AI 时代的可视化工作流利器告别“微信黑箱”!Chatlog:让你的聊天记录也能拥有“AI大脑”!字节跳动 Seed-Coder-8B:不靠人工洗数据,这80亿参数的小模型如何写出顶尖代码?
无须邀请码的OpenManus来了:手把手教你部署开源版「AI智能体革命」 常见的十大排序算法解析 阿里云万相2.1:开源视频生成模型的全面解析 美团外卖搭上 DeepSeek 这趟 AI 快车,外卖界要变天啦! JAVA当中的异常处理机制核心讲解 Llama 4:参数屠榜还是数据注水?AI 圈的最新‘瓜’熟了没?
标签聚合
设计模式 教程 算法 java deepseek 动态规划 AI spring

COPYRIGHT © 2023 墨风如雪博客. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

免责声明 - 隐私政策