当前位置: 首页 > news >正文

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限:

// 抽象处理者:审批者
abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者public void setSuccessor(Approver successor) {this.successor = successor;}// 处理请求的抽象方法public abstract void processRequest(PurchaseRequest request);
}// 具体处理者:主任
class Director extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 10000) {System.out.println("主任审批了金额为 " + request.getAmount() + " 的采购申请");} else if (successor != null) {successor.processRequest(request);}}
}// 具体处理者:经理
class Manager extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 50000) {System.out.println("经理审批了金额为 " + request.getAmount() + " 的采购申请");} else if (successor != null) {successor.processRequest(request);}}
}// 具体处理者:副总裁
class VicePresident extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 100000) {System.out.println("副总裁审批了金额为 " + request.getAmount() + " 的采购申请");} else if (successor != null) {successor.processRequest(request);}}
}// 具体处理者:总裁
class President extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 500000) {System.out.println("总裁审批了金额为 " + request.getAmount() + " 的采购申请");} else {System.out.println("金额过大,需要董事会讨论");}}
}// 请求类
class PurchaseRequest {private double amount; // 金额private String purpose; // 用途public PurchaseRequest(double amount, String purpose) {this.amount = amount;this.purpose = purpose;}public double getAmount() {return amount;}public String getPurpose() {return purpose;}
}// 客户端类
public class Client {public static void main(String[] args) {// 创建处理者Approver director = new Director();Approver manager = new Manager();Approver vicePresident = new VicePresident();Approver president = new President();// 设置责任链director.setSuccessor(manager);manager.setSuccessor(vicePresident);vicePresident.setSuccessor(president);// 创建采购申请PurchaseRequest request1 = new PurchaseRequest(5000, "购买办公用品");PurchaseRequest request2 = new PurchaseRequest(30000, "购买电脑设备");PurchaseRequest request3 = new PurchaseRequest(80000, "购买服务器");PurchaseRequest request4 = new PurchaseRequest(300000, "购买办公大楼");// 处理请求director.processRequest(request1);director.processRequest(request2);director.processRequest(request3);director.processRequest(request4);}
}

一、能不能连写?

// 抽象处理者:审批者
abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者并返回当前实例public Approver setSuccessor(Approver successor) {this.successor = successor;return this;}// 处理请求的抽象方法public abstract void processRequest(PurchaseRequest request);
}// 具体处理者:主任
class Director extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 10000) {System.out.println("主任审批了金额为 " + request.getAmount() + " 的采购申请");} else if (successor != null) {successor.processRequest(request);}}
}// 具体处理者:经理
class Manager extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 50000) {System.out.println("经理审批了金额为 " + request.getAmount() + " 的采购申请");} else if (successor != null) {successor.processRequest(request);}}
}// 具体处理者:副总裁
class VicePresident extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 100000) {System.out.println("副总裁审批了金额为 " + request.getAmount() + " 的采购申请");} else if (successor != null) {successor.processRequest(request);}}
}// 具体处理者:总裁
class President extends Approver {@Overridepublic void processRequest(PurchaseRequest request) {if (request.getAmount() < 500000) {System.out.println("总裁审批了金额为 " + request.getAmount() + " 的采购申请");} else {System.out.println("金额过大,需要董事会讨论");}}
}// 请求类
class PurchaseRequest {private double amount; // 金额private String purpose; // 用途public PurchaseRequest(double amount, String purpose) {this.amount = amount;this.purpose = purpose;}public double getAmount() {return amount;}public String getPurpose() {return purpose;}
}// 客户端类
public class Client {public static void main(String[] args) {// 创建处理者Approver director = new Director();Approver manager = new Manager();Approver vicePresident = new VicePresident();Approver president = new President();// 链式设置责任链director.setSuccessor(manager).setSuccessor(vicePresident).setSuccessor(president);// 创建采购申请PurchaseRequest request1 = new PurchaseRequest(5000, "购买办公用品");PurchaseRequest request2 = new PurchaseRequest(30000, "购买电脑设备");PurchaseRequest request3 = new PurchaseRequest(80000, "购买服务器");PurchaseRequest request4 = new PurchaseRequest(300000, "购买办公大楼");// 处理请求director.processRequest(request1);director.processRequest(request2);director.processRequest(request3);director.processRequest(request4);}
}

主要改动点

  1. Approver抽象类里,把setSuccessor方法的返回值类型改成了Approver,并让它返回this
  2. 客户端代码中的责任链设置从原来的逐行调用转变为链式调用,极大地提升了代码的可读性。

注意事项

  • 链式调用的本质是,后一个处理者会覆盖前一个处理者设置的successor。在这个例子中,真正生效的责任链是vicePresident -> president
  • 要构建正确的责任链,应该按照director -> manager -> vicePresident -> president这样的顺序来设置。你可以通过以下方式实现:
director.setSuccessor(manager);
manager.setSuccessor(vicePresident);
vicePresident.setSuccessor(president);

二、return this;返回的是谁?

在责任链模式的代码里,return this;返回的是当前正在执行setSuccessor方法的处理者实例。下面结合具体例子详细说明:

1. setSuccessor方法的返回值

Approver抽象类中,setSuccessor方法经过修改后返回this

public Approver setSuccessor(Approver successor) {this.successor = successor;return this; // 返回当前处理者实例
}
  • this的含义:在某个具体处理者(像DirectorManager等)调用setSuccessor方法时,this指的就是该处理者对象。

2. 链式调用的执行流程

来看客户端代码里的链式调用:

director.setSuccessor(manager).setSuccessor(vicePresident).setSuccessor(president);

执行步骤如下

⑴.director.setSuccessor(manager)

  • manager设为director的下一个处理者。
  • 返回director对象(也就是this)。

⑵.setSuccessor(vicePresident)

  • 由于第一步返回的是director,所以这里实际上是director.setSuccessor(vicePresident)
  • 这就会覆盖掉director原来的successor(原本是manager),将其更新为vicePresident
  • 再次返回director对象。

⑶.setSuccessor(president)

  • 同理,这里是director.setSuccessor(president)
  • 又一次覆盖directorsuccessor,现在变成了president
  • 还是返回director对象。

3. 最终形成的责任链

经过上述链式调用后,责任链的结构是:

director → president
  • 问题所在managervicePresident被排除在了责任链之外,这显然不是我们期望的结果。

4. 正确构建责任链的方法

要构建director → manager → vicePresident → president这样正确的责任链,应该依次设置每个处理者的下一个处理者:

director.setSuccessor(manager);  // director 的下一个是 manager
manager.setSuccessor(vicePresident);  // manager 的下一个是 vicePresident
vicePresident.setSuccessor(president);  // vicePresident 的下一个是 president

5.总结

  • return this的作用:它使得方法可以被链式调用,但在构建责任链时,必须谨慎使用,保证每个处理者的successor设置正确。
  • 常见错误:直接链式调用setSuccessor会导致前面设置的successor被覆盖,就像例子中最后只有director → president这一条链路。

三、successor被覆盖是什么意思?

在责任链模式中,"successor 被覆盖" 指的是在设置处理者链时,由于错误地使用链式调用,导致先前设置的下一个处理者(successor)被后续操作意外替换的情况。以下通过具体示例详细解释:

1. 正确的责任链设置

责任链模式要求每个处理者的successor指向下一个正确的处理者。例如:

director.setSuccessor(manager);     // director → manager
manager.setSuccessor(vicePresident); // manager → vicePresident
vicePresident.setSuccessor(president); // vicePresident → president

此时的责任链结构为:

director → manager → vicePresident → president

2. 错误的链式调用导致覆盖问题

如果误用链式调用,例如:

director.setSuccessor(manager).setSuccessor(vicePresident).setSuccessor(president);

执行过程分解

  1. director.setSuccessor(manager)

    • directorsuccessor被设为manager
    • 方法返回director(即this)。
  2. .setSuccessor(vicePresident)

    • 由于返回的是director,实际执行的是director.setSuccessor(vicePresident)
    • 覆盖了第一步设置的successor,现在directorsuccessor变成vicePresidentmanager被排除
  3. .setSuccessor(president)

    • 同理,执行director.setSuccessor(president)
    • 再次覆盖directorsuccessor最终变为presidentvicePresident也被排除

最终责任链结构

director → president

中间的managervicePresident被完全跳过,这就是 **"successor 被覆盖"** 的结果。

3. 为什么会被覆盖?

  • return this的副作用
    在链式调用中,每次调用setSuccessor都返回当前处理者(如director),导致后续的setSuccessor总是作用于同一个处理者(如director),从而覆盖之前的设置。

  • 正确链式调用的写法
    如果要使用链式语法,必须确保每次调用返回不同的处理者

director.setSuccessor(manager);        // 返回 director(忽略)
manager.setSuccessor(vicePresident);   // 返回 manager(忽略)
vicePresident.setSuccessor(president); // 返回 vicePresident(忽略)

这种写法虽然语法上是链式的,但实际是分步骤设置不同处理者的 successor,避免覆盖。

相关文章:

  • Odoo 18 定期发送电子邮件报告(如KPI)配置指南
  • vivo y300pro 无法连接adb
  • C++语法系列之IO流
  • Linux网络协议栈:从Socket到网卡的星辰大海
  • python实现合并多个dot文件
  • 【AI系列】DPO 与 PPO 的比较与分析
  • 标准IO及相关函数介绍
  • Efficient RAW Image Deblurring with Adaptive Frequency Modulation
  • 龙虎榜——20250604
  • 网络攻防技术十四:入侵检测与网络欺骗
  • 我也不知道
  • 共识机制全景图:PoW、PoS 与 DAG 的技术对比
  • c++第6天--运算符重载
  • 短剧+小说网盘搜索系统(支持全网网盘转存拉新)
  • LeetCode 热题 100 739. 每日温度
  • Rhino
  • 嵌入式学习笔记 - freeRTOS任务设计要点
  • GuessNumber
  • Python网络设备批量配置脚本解析
  • 蓝桥云课ROS一键配置teb教程更新-250604
  • 网站建设的目的及功能/宁波seo快速优化平台
  • 做网站需要备案吗/口碑营销方案怎么写
  • 4399小游戏大全网页版/如何优化网络延迟
  • wordpress博客vieu/seo测试工具
  • 南昌网站设计专业/百度平台商家联系方式
  • 免费一键生成短链接/重庆seo代理计费