行为型设计模式08-职责链模式

news2024/10/6 6:49:53

🧑‍💻作者:猫十二懿

❤️‍🔥账号:CSDN 、掘金 、个人博客 、Github

🎉公众号:猫十二懿

职责链模式

1、职责链模式介绍

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

在责任链模式中,请求通过一条链传递,每个对象都有机会处理请求。当一个对象无法处理请求时,它会将请求传递给链中的下一个对象,直到找到能够处理请求的对象为止。这种方式可以动态地组织和管理对象,使得请求发送者和接收者之间解耦,提高系统的灵活性和可扩展性。

1.1 职责链模式基本实现

职责链模式结构图:

image-20230520160258279

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

  1. 抽象处理者(Handler):定义了一个处理请求的接口,通常包含一个指向下一个处理者的引用,用于构建责任链。
  2. 具体处理者(ConcreteHandler):实现抽象处理者接口,具体处理请求的逻辑。如果可以处理请求,则处理请求;否则,将请求传递给下一个处理者。

Handler类,定义一个处理请示的接口:

/**
 * @author Shier
 * CreateTime 2023/5/20 16:04
 * 处理请求的接口
 */
public abstract class Handler {
    protected Handler successor;

    /**
     * 设置继承者
     * @param successor
     */
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    public abstract void handleRequest(int request);
}

ConcreteHandler类,具体处理者类,处理它所负责的请求,可访问它的 后继者,如果可处理该请求,就处理之,否则就将该请求转发给它的后继 者。

ConcreteHandler1,当请求数为0~10则有权处理,否则转到下一位:

/**
 * @author Shier
 * CreateTime 2023/5/20 16:06
 */
public class ConcreteHandler1 extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 0 && request < 10) {
            // 当前处理者权限 0 ~ 9
            System.out.println(this.getClass().getSimpleName() + "处理了请求" + request);
        } else if (successor != null) {
            // 转移给下一个处理者
            successor.handleRequest(request);
        }
    }
}

ConcreteHandler2,当请求数为10~20则有权处理,否则转到下一位。

/**
 * @author Shier
 * CreateTime 2023/5/20 16:06
 */
public class ConcreteHandler2 extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 10 && request < 20) {
            // 当前处理者权限 10 ~ 19
            System.out.println(this.getClass().getSimpleName() + "处理了请求" + request);
        } else if (successor != null) {
            // 转移给下一个处理者
            successor.handleRequest(request);
        }
    }
}

ConcreteHandler3,当请求数为20~99则有权处理,否则转到下一位

/**
 * @author Shier
 * CreateTime 2023/5/20 16:06
 */
public class ConcreteHandler3 extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 20 && request < 100) {
            // 当前处理者权限 20 ~ 99
            System.out.println(this.getClass().getSimpleName() + "处理了请求" + request);
        } else if (successor != null) {
            // 转移给下一个处理者
            successor.handleRequest(request);
        }
    }
}

客户端代码,向链上的具体处理者对象提交请求。

/**
 * @author Shier
 * CreateTime 2023/5/20 16:09
 */
public class ChainClient {
    public static void main(String[] args) {
        ConcreteHandler1 handler1 = new ConcreteHandler1();
        ConcreteHandler2 handler2 = new ConcreteHandler2();
        ConcreteHandler3 handler3 = new ConcreteHandler3();
        // 设置职责链上下关系
        handler1.setSuccessor(handler2);
        handler2.setSuccessor(handler3);

        // 请求
        int[] request = {15, 67, 8, 9, 46, 1, 5, 23, 41};

        // 循环给最小矗立着提交请求,不同的数额,得不同的权限处理者处理
        for (int i : request) {
            handler1.handleRequest(i);
        }
    }
}

2、具体例子说明

在公司请假或者升职加薪,需要通过经理、总监、总经理的批准,不同身份有不同的权限。当然可以直接直接找总经理给你升职加薪😎

2.1 不使用职责链模式 - 加薪 / 请假

升值加薪:经理是没有权限的,要上报给总监,总监的回复也是没有权限管,只能再上报到总经理才有处理的权限

请假:经理只能处理请假两天的申请,再多就不可以。必须要上报给上司才有权限去处理这个请求。

// 申请类
public class Request {
    // 申请类别
    private String requestType;
    public String getRequestType(){
        return this.requestType;
    }
    public void setRequestType(String value){
        this.requestType = value;
    }

    //申请内容
    private String requestContent;
    public String getRequestContent(){
        return this.requestContent;
    }
    public void setRequestContent(String value){
        this.requestContent = value;
    }

    // 数量
    private int number;
    public int getNumber(){
        return this.number;
    }
    public void setNumber(int value){
        this.number = value;
    }
}
//管理者
public class Manager{
    protected String name;
    public Manager(String name){
        this.name = name;
    }
    public void getResult(String managerLevel,Request request){
        if (managerLevel == "经理"){
          if (request.getRequestType()=="请假" && request.getNumber()<=2)
            System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,被批准");
          else 
            System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,我无权处理");
        }
        else if (managerLevel == "总监"){
          if (request.getRequestType()=="请假" && request.getNumber()<=5)
            System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,被批准");
          else 
            System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,我无权处理");
        }
        else if (managerLevel == "总经理"){
          if (request.getRequestType()=="请假")
            System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,被批准");
          else if (request.getRequestType()=="加薪" && request.getNumber()<=5000)
            System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"元,被批准");
          else if (request.getRequestType()=="加薪" && request.getNumber()>5000)
            System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"元,再说吧");
        }
    }
}

客户端:

public class Test {
    public static void main(String[] args) {
        Manager manager = new Manager("金利");
        Manager director = new Manager("宗剑");
        Manager generalManager = new Manager("钟精励");

        Request request = new Request();
        request.setRequestType("加薪");
        request.setRequestContent("Shier请求加薪");
        request.setNumber(10000); 
        // 不同身份的人有不同的权限,进行处理结果
        manager.getResult("经理", request);
        director.getResult("总监", request);
        generalManager.getResult("总经理", request);

        Request request2 = new Request();
        request2.setRequestType("请假");
        request2.setRequestContent("Shier请假");
        request2.setNumber(3); // 权限级别

        manager.getResult("经理", request2);
        director.getResult("总监", request2);
        generalManager.getResult("总经理", request2);
    }
}

通过上面的程序,会发现一个问题管理者类,里面的方法比较长,太多的分支判断。类的责任太多,就违背了单一职责原则,同时增加新的项目时,要去修改这个方法,就违背了开发 - 封闭原则。下面就要用到职责链模式要简化这样开发业务场景 。

2.2 职责链模式 - 加薪 / 请假

将上面的程序进行重构,得到的代码结构图如下:

image-20230520163053788

Request请求类:

/**
 * @author Shier
 * 申请类
 */
public class Request {
    // 申请类别
    private String requestType;

    public String getRequestType() {
        return this.requestType;
    }

    public void setRequestType(String value) {
        this.requestType = value;
    }

    //申请内容
    private String requestContent;

    public String getRequestContent() {
        return this.requestContent;
    }

    public void setRequestContent(String value) {
        this.requestContent = value;
    }

    // 数量
    private int number;

    public int getNumber() {
        return this.number;
    }

    public void setNumber(int value) {
        this.number = value;
    }
}

抽象管理者:

/**
 * @author Shier
 * CreateTime 2023/5/20 16:33
 * 抽象管理这类
 */
public abstract class Manager {
    protected String name;

    public Manager(String name) {
        this.name = name;
    }

    /**
     * 设置管理者上级
     */
    protected Manager superior;

    public void setSuperior(Manager superior) {
        this.superior = superior;
    }

    /**
     * 请求申请
     *
     * @param request
     */
    public abstract void requestApplications(Request request);
}

经理类就可以去继承这个’管理者’类,只需重写 ‘申请请求’ 的方法

/**
 * @author Shier
 * CreateTime 2023/5/20 16:34
 * 普通经理类
 */
public class CommonManager extends Manager {
    public CommonManager(String name) {
        super(name);
    }

    @Override
    public void requestApplications(Request request) {
        if (request.getRequestType() == "请假" && request.getNumber() <= 2) {
            System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "天,被批准");
        } else if (this.superior != null) {
            this.superior.requestApplications(request);
        }
    }
}

总监同样继承抽象管理类

/**
 * @author Shier
 * CreateTime 2023/5/20 16:36
 * 总监
 */
public class Director extends Manager {
    public Director(String name) {
        super(name);
    }

    @Override
    public void requestApplications(Request request) {
        if (request.getRequestType() == "请假" && request.getNumber() <= 5) {
            System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "天,被批准");
        } else if (this.superior != null) {
            this.superior.requestApplications(request);
        }
    }
}

总经理同样继承管理者类,总经理的权限就是全部都需要处理。

/**
 * @author Shier
 * CreateTime 2023/5/20 16:36
 * 总经理
 */
public class GeneralManager extends Manager {
    public GeneralManager(String name) {
        super(name);
    }

    @Override
    public void requestApplications(Request request) {
        if (request.getRequestType() == "请假") {
            System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "天,被批准");
        } else if (request.getRequestType() == "加薪" && request.getNumber() <= 5000) {
            System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "元,被批准");
        } else if (request.getRequestType() == "加薪" && request.getNumber() > 5000) {
            System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "元,再说吧");
        }
    }
}

测试类:

/**
 * @author Shier
 */
public class ChainClient {
    public static void main(String[] args) {

        CommonManager manager = new CommonManager("大明经理");
        Director director = new Director("大大明总监");
        GeneralManager generalManager = new GeneralManager("大大大明总经理");

        // 设置管理者之间上下级关系 经理 => 总监 => 总经理
        manager.setSuperior(director);
        director.setSuperior(generalManager);

        // 加薪 5000
        Request request = new Request();
        request.setRequestType("加薪");
        request.setRequestContent("Shier请求加薪");
        request.setNumber(5000);
        // 从自己最近的上司开始请求也就是经理
        manager.requestApplications(request);

        // 加薪10000
        Request request1 = new Request();
        request1.setRequestType("加薪");
        request1.setRequestContent("Shier请求加薪");
        request1.setNumber(10000);
        manager.requestApplications(request1);

        // 请假一天
        Request request2 = new Request();
        request2.setRequestType("请假");
        request2.setRequestContent("Shier请假");
        request2.setNumber(1);
        manager.requestApplications(request2);

        // 请假四天
        Request request3 = new Request();
        request3.setRequestType("请假");
        request3.setRequestContent("Shier请假");
        request3.setNumber(4);
        manager.requestApplications(request3);

    }
}

最后得到的结果:

chain

由于我们把原来的一个 ‘管理者’ 类改成了一个抽象类和三个具体类, 此时类之间的灵活性就大大增加了,如果我们需要扩展新的管理者类别,只需要增加子类就可以。比如这个例子增加一个 ‘集团总裁’ 类,完全是没有问题的,只需要修改 ‘总经理类’ 即可,并不影响其他类代码。

这样使用职责链模式可以更加清晰这些代码之间的关系,不像最上面的一个类里面多个判断语句,看起来都很难维护。好了,再总结一下职责链模式

3、职责链模式总结

职责链模式的好处

  1. 当客户提交一个请求时,请求是沿链传递直至有一个 ConcreteHandler 对象负责处理它。
  2. 降低耦合:接收者和发送者都没有对方的明确信息,且链中的对 象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅 需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。降低了代码之间耦合度。
  3. 灵活性:随时地增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。

优点:

  1. 将请求发送者和接收者解耦,可以避免请求发送者与接收者之间的直接耦合,增强了代码的可维护性。
  2. 可以动态地新增或修改请求处理顺序,提高了程序的灵活性和可扩展性。
  3. 可以进行请求的拦截、分流等操作,方便进行统计和日志记录等处理。
  4. 可以根据需要对请求的处理进行单独的测试,便于代码测试和调试。
  5. 解耦发送者和接收者:职责链模式可以将发送者和接收者解耦,发送者不需要知道请求的具体处理者是谁,而处理者也不需要知道请求的发送者是谁,从而提高系统的灵活性。
  6. 动态组合和扩展性:职责链模式允许动态地向链中添加或删除处理者,以适应不同的业务需求,增强了系统的可扩展性。
  7. 可配置性:通过调整链中处理者的顺序,可以灵活地配置处理流程,满足不同的处理优先级或条件。

缺点:

  1. 请求的保证:没有明确的处理者处理请求的保证。请求可能到达链的末尾而没有被处理,这需要在设计时进行合理的考虑。
  2. 性能考虑:由于链中的请求需要依次传递给每个处理者,因此在处理大量请求时可能会影响性能。
  3. 可能导致系统变得复杂:当链过长或者处理者过多时,职责链模式可能会导致系统变得复杂,难以理解和维护。

使用场景:

  1. 处理复杂的请求处理流程,例如购物车结算、审批流程等复杂业务中。

  2. 需要动态指定请求的处理顺序或者动态添加新的请求处理者时。

  3. 处理日志记录、缓存等拦截器的场景。例如在Spring中,就应用了责任链模式来实现Interceptor拦截器。

  4. 多个对象可以处理同一请求,但具体的处理者在运行时可变或不确定的情况下,可以使用职责链模式。

  5. 需要动态组合处理流程或动态调整处理顺序的情况下,职责链模式可以提供灵活性和可配置性。

  6. 需要在不明确请求的发送者和接收者之间建立松耦合关系的情况下,职责链模式可以解耦对象之间的关系。

  7. 可配置性:通过调整链中处理者的顺序,可以灵活地配置处理流程,满足不同的处理优先级或条件。

缺点:

  1. 请求的保证:没有明确的处理者处理请求的保证。请求可能到达链的末尾而没有被处理,这需要在设计时进行合理的考虑。
  2. 性能考虑:由于链中的请求需要依次传递给每个处理者,因此在处理大量请求时可能会影响性能。
  3. 可能导致系统变得复杂:当链过长或者处理者过多时,职责链模式可能会导致系统变得复杂,难以理解和维护。

使用场景:

  1. 处理复杂的请求处理流程,例如购物车结算、审批流程等复杂业务中。
  2. 需要动态指定请求的处理顺序或者动态添加新的请求处理者时。
  3. 处理日志记录、缓存等拦截器的场景。例如在Spring中,就应用了责任链模式来实现Interceptor拦截器。
  4. 多个对象可以处理同一请求,但具体的处理者在运行时可变或不确定的情况下,可以使用职责链模式。
  5. 需要动态组合处理流程或动态调整处理顺序的情况下,职责链模式可以提供灵活性和可配置性。
  6. 需要在不明确请求的发送者和接收者之间建立松耦合关系的情况下,职责链模式可以解耦对象之间的关系。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/642760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

seatunnel入门案例,集群模式

目录 安装部署 解压 环境变量 安装plugin 添加资源jar包 SEATUNNEL 配置文件 env&#xff1a;环境设置 source&#xff1a;数据源设置 sink&#xff1a;数据去向设置 transform: 数据转换设置 运行方式 seatunnel 引擎(zeta) 本地模式 集群模式 安装部署 解压 tar…

Centos7在Nginx中配置SSL证书

我的环境 阿里云轻量应用服务器&#xff08;Linux, Centos7.9 x64&#xff09; 一、申请免费SSL证书 一年可以创建20个 下载证书&#xff08;我是Nginx服务器&#xff09; 下载到本地后&#xff0c;打开有两个文件&#xff1a; 二、将SSL证书文件上传至服务器 通过WinScp拖…

图像sensor的特性和驱动解析

1、更换OV9712并且做配置更改和测试 1.1、更改配置脚本 修改Hi3518E_SDK_V1.0.3.0\package\mpp\sample\Makefile.param 1.2、测试运行 运行官方SDK sample的测试版本&#xff08;打包到本地&#xff09; 运行ORTP传输的测试版本&#xff08;RTP实时预览&#xff09; 1.3、更…

如何高效合理规划每天的工作?

如何高效合理规划每天的工作&#xff1f; 〇、基本原则 梳理工作&#xff0c;明确目标。&#xff08;SMART法则&#xff09;轻重缓急&#xff0c;排优先级。&#xff08;四象限管理法则&#xff09;要事第一&#xff0c;尽管去做。&#xff08;GTD 理论&#xff09;限时deadl…

新买的电脑怎么用U盘重装系统?新买的电脑用U盘重装系统教程

新买的电脑怎么用U盘重装系统&#xff1f;用户新买了电脑&#xff0c;想知道怎么用U盘来重装新买的电脑&#xff0c;用U盘来重装电脑其实非常简单&#xff0c;用户需要准备一个U盘&#xff0c;然后完成U盘启动盘的安装&#xff0c;接着按照以下分享的新买的电脑用U盘重装系统教…

[Hadoop安装配置 ]

目录 前言: 执行步骤: 1 创建好目录文件,上传Hadoop版本压缩包,一般都是tar.gz 结尾包 1.1这里压缩包可以直接拖拽到指定虚拟机目录下, 例如xshell连接指定虚拟机, 然后可以拖拽,如果拖拽不了,那就需要设置一下配置, 或者 使用 xftp工具 连接xshell 然后上传文件 2 解压…

pandas---数据合并(concat、append、merge)

1. concat函数 pd.concat([data1, data2], axis1) 按照行或列进行合并&#xff0c;axis0为列索引&#xff0c;axis1为行索引。 df1 make_df([1, 2], [A, B]) df2 make_df([3, 4], [A, B]) display(df1, df2) # 默认上下合并&#xff0c;垂直合并 pd.concat([df1, df2]) …

【机器学习】——学习的基本分类:算法模拟的根本出发点!

目录 引入 一、分类 1、基于学习策略的分类 2、基于所获取知识的表示形式分类 3、按应用领域分类 4、综合分类 二、研究领域 引入 机器学习是继专家系统后人工智能的又一重要研究领域&#xff01;机器学习是研究计算机怎样模拟或实现人类的学习行为&#xff0c;以获取新…

前端面试经验技巧分享

&#x1f469; 个人主页&#xff1a;不爱吃糖的程序媛 &#x1f64b;‍♂️ 作者简介&#xff1a;前端领域新星创作者、CSDN内容合伙人&#xff0c;专注于前端各领域技术&#xff0c;成长的路上共同学习共同进步&#xff0c;一起加油呀&#xff01; ✨系列专栏&#xff1a;前端…

NVIDIA的StyleGAN、StyleGAN2、StyleGAN3系列论文解读,梳理基于风格的生成器架构

通俗来讲就是&#xff0c;张三造假币(Generator生成器)&#xff0c;然后用验钞机去验证真假(Discriminator辨别器)&#xff0c;如果是假的就继续提高造假技术&#xff0c;直到验钞机检验不出来为止&#xff0c;也就是说一个造假一个验假(验钞机也需升级)&#xff0c;两者互相学…

Redis集群部署

Redis集群部署 1.单机安装Redis2.Redis主从集群2.1.集群结构2.2.准备实例和配置2.3.启动2.4.开启主从关系2.5.测试 3.搭建哨兵集群3.1.集群结构3.2.准备实例和配置3.3.启动3.4.测试 4.搭建分片集群4.1.集群结构4.2.准备实例和配置4.3.启动4.4.创建集群4.5.测试4.5.测试 本章是基…

安全 --- 内网基础知识(01)

内网基础知识 &#xff08;1&#xff09;概念 内网也称局域网&#xff08;Local Area Network&#xff0c;LAN&#xff09;是指在某一工作区域内由多台计算机互联形成的计算机组&#xff0c;一般是方圆几千米内。局域网可实现文件管理、应用软件共享、打印机共享、工作内的历…

新一代绿色智慧数据中心电气规划设计与常识(一)

绿色智慧数据中心 随着大数据、云计算、人工智能、区块链、ChatGPT等技术加速创新&#xff0c;数字文化产业发展动力强劲&#xff0c;不断解锁新兴业态。近年来&#xff0c;各级政府重要会议中也多次强调“新基建”今后一段时期驱动新一轮产业革命的战略性新兴产业&#xff0c…

软件测试06:软件测试原则和黑盒测试用例设计方法

软件测试原则 所有测试的标准都是建立在用户需求之上软件测试必须基于"质量第一"的思想去开展各项工作&#xff0c;当时间和质量冲突时&#xff0c;时间要服从质量事先定义好产品的质量标准&#xff0c;只有有了质量标准&#xff0c;才嫩如果根据测试的结果&#xf…

今年找工作真的好难啊,一秒泪崩

在入行前端开发之前&#xff0c;我看过了很多从学校毕业之后一事无成的人&#xff0c;而我心气比较高&#xff0c;接受不了自己也一样浑浑噩噩地过。偶然机会接触到了前端开发&#xff0c;觉得很有意思&#xff0c;思考再三之后&#xff0c;决定去做这件自己喜欢又能有所成就的…

散热差、设计古板,因循守旧的联想Thinkpad还能获得忠粉的青睐吗?

拥有航天梦想的联想ThinkPad&#xff0c;在5月18日的新品发布会上&#xff0c;再次与中国航天太空创想达成了合作&#xff0c;将整场发布会的格调提升到了没有“边际”的高度。 发布会上&#xff0c;联想ThinkPad宣布了几款新品的面世&#xff0c;产品性能的升级和优化必不可少…

ICASSP 2023 | 深度窄带网络消除实时语音通信中的干扰音

来源&#xff1a;ICASSP 2023 作者&#xff1a;Feifei Xiong, Jinwei Feng等 论文题目&#xff1a;Deep Subband Network for Joint Suppression of Echo, Noise and Reverberation in Real-Time Fullband Speech Communication 本文由阿里巴巴钉钉蜂鸣鸟音频实验室&#xff08…

使用vuex记住当前页面页码信息,以便从详情页返回列表页时能还原到上一次页面

文章目录 一、在vuex中需要完成的工作二、在需要记住页面信息的列表页组件中添加如下代码&#xff0c;比如list.vue:三、在详情页添加返回按钮&#xff08;可选&#xff09;四、顺便来总结下&#xff0c;能返回上一级页面的方法有2类5种&#xff1a;五、总结&#xff0c;记住当…

移动设备管理:自带设备办公(BYOD)管理

什么是自带设备办公&#xff08;BYOD&#xff09; 自带设备办公&#xff08;BYOD&#xff09;指一些企业允许员工携带自己的笔记本电脑、平板电脑、智能手机等移动终端设备到办公场所&#xff0c;并可以用这些设备获取公司内部信息、使用企业特许应用的一种政策&#xff0c;企…

支持AUTOSAR Classic以及Adaptive平台的DEXT诊断数据库

一 DEXT、DCM、DEM和FIM的概述 DEXT&#xff08;Diagnostic Extract Template&#xff09;是AUTOSAR定义的诊断提取模板&#xff0c;用于DCM&#xff08;Diagnostics Communication Manager&#xff09;、DEM&#xff08;Diagnostics Event Manager&#xff09;和FIM&#xff…