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 {
    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 10000) {
            System.out.println("主任审批了金额为 " + request.getAmount() + " 的采购申请");
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理者:经理
class Manager extends Approver {
    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 50000) {
            System.out.println("经理审批了金额为 " + request.getAmount() + " 的采购申请");
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理者:副总裁
class VicePresident extends Approver {
    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 100000) {
            System.out.println("副总裁审批了金额为 " + request.getAmount() + " 的采购申请");
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理者:总裁
class President extends Approver {
    @Override
    public 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 {
    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 10000) {
            System.out.println("主任审批了金额为 " + request.getAmount() + " 的采购申请");
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理者:经理
class Manager extends Approver {
    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 50000) {
            System.out.println("经理审批了金额为 " + request.getAmount() + " 的采购申请");
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理者:副总裁
class VicePresident extends Approver {
    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 100000) {
            System.out.println("副总裁审批了金额为 " + request.getAmount() + " 的采购申请");
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}

// 具体处理者:总裁
class President extends Approver {
    @Override
    public 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,避免覆盖。

相关推荐
RainbowJie113 分钟前
从零到一:Maven 快速入门教程
java·maven
shangjg317 分钟前
Kafka数据怎么保障不丢失
java·分布式·后端·kafka
RainbowJie121 分钟前
Maven的生命周期
java·maven
唐墨12325 分钟前
PublishSubject、ReplaySubject、BehaviorSubject、AsyncSubject的区别
java·后端·spring
何中应26 分钟前
【设计模式-3.7】结构型——组合模式
java·设计模式·组合模式
爬菜30 分钟前
JUnit
java
敲键盘的小夜猫33 分钟前
RunnablePassthrough介绍和透传参数实战
java·服务器·前端
景天科技苑35 分钟前
【Rust宏编程】Rust有关宏编程底层原理解析与应用实战
开发语言·后端·rust·rust宏·宏编程·rust宏编程
码农开荒路1 小时前
Redis底层数据结构之字典(Dict)
java·数据结构·数据库·redis
yorushika_1 小时前
python打卡训练营打卡记录day45
开发语言·python·深度学习·tensorboard