java iterator 遍历责任链的核心做法是:在责任链的每个 handler 中实现 iterator<handler></handler> 接口,通过 next() 返回下一个节点,hasnext() 判断是否结束。调用方只需获取链头节点的迭代器,即可用标准循环结构(如 while)统一处理所有节点,无需关心内部是链表、数组还是树状结构。这种设计将遍历逻辑与业务逻辑解耦,符合开闭原则。

如何定义支持迭代的 Handler 节点
要实现可迭代的 Handler,最直接的方式是让 Handler 类实现 java.util.Iterator<handler></handler> 接口。你需要维护一个指向下一个节点的引用 nextHandler,并在 next() 方法中返回该引用,同时更新自身状态或保持引用不变(取决于具体实现策略,通常责任链是静态结构,所以直接返回 nextHandler 即可)。如果 nextHandler 为空,则 hasNext() 返回 false。这样,任何一个 Handler 实例都可以作为链表的起点进行遍历。

public abstract class AbstractHandler implements Iterator<AbstractHandler> {
protected AbstractHandler nextHandler;
public void setNext(AbstractHandler handler) {
this.nextHandler = handler;
}
@Override
public boolean hasNext() {
return nextHandler != null;
}
@Override
public AbstractHandler next() {
if (!hasNext()) throw new NoSuchElementException();
return nextHandler;
}
public abstract void handleRequest(String request);
}
上述代码展示了基础抽象类。它定义了 nextHandler 字段和设置方法。关键点是 Iterator 接口的实现:hasNext() 检查是否有后继者,next() 返回后继者并推进“指针”(这里因为是单向链表且通常不修改结构,直接返回下一个节点即可,若需原地推进可引入索引或临时变量,但简单责任链通常由调用方控制流程或节点内部自行决定传递)。在实际使用中,我们通常让具体的 Handler 继承此类。
立即学习“Java免费学习笔记(深入)”;
如何在客户端代码中统一遍历责任链
一旦 Handler 实现了 Iterator,客户端代码就可以使用标准的迭代模式来执行整个链条。你只需要持有链头的引用,然后调用其 iterator() 方法(或直接将其作为 Iterator 使用),通过 while(hasNext()) 循环逐个获取节点并调用其 handleRequest 方法。这种方式比递归调用更直观,且避免了栈溢出的风险,特别是当责任链非常长时。此外,由于每个节点都是 Iterator,你也可以从链中的任意位置开始遍历,提供了极大的灵活性。

public class Client {
public static void main(String[] args) {
// 构建责任链
AbstractHandler h1 = new ConcreteHandlerA();
AbstractHandler h2 = new ConcreteHandlerB();
AbstractHandler h3 = new ConcreteHandlerC();
h1.setNext(h2);
h2.setNext(h3);
// 使用 Iterator 遍历
AbstractHandler current = h1;
while (current.hasNext()) {
System.out.println("Processing at: " + current.getClass().getSimpleName());
current.handleRequest("Test Request");
current = current.next(); // 移动到下一个节点
}
// 处理最后一个节点
System.out.println("Processing at: " + current.getClass().getSimpleName());
current.handleRequest("Test Request");
}
}
这段代码演示了典型的遍历过程。注意,while(current.hasNext()) 循环只处理到倒数第二个节点,因为 hasNext() 为 true 时才进入循环,而 next() 返回的是下一个节点。因此,循环结束后,current 指向最后一个节点,需要额外调用一次 handleRequest。或者,你可以重构逻辑,让 next() 返回当前节点并推进,但这会改变 Iterator 的标准语义。更常见的做法是在 Handler 内部封装执行逻辑,或者在客户端使用增强 for 循环(如果 Java 版本支持自定义 Iterable,但 Iterator 本身不能直接用于 for-each,除非包装成 Iterable)。上面的示例是最直接的 Iterator 用法。
当责任链中存在循环引用时 Iterator 会怎样
如果责任链被错误地配置成循环引用(例如 A->B->A),标准的 Iterator 实现会导致无限循环。因为 hasNext() 永远返回 true,next() 不断返回已访问过的节点。为了避免这种情况,可以在 AbstractHandler 中增加一个 visited 集合或使用版本号机制,或者在遍历时由客户端记录已访问的节点 ID。另一种更安全的做法是使用 Iterable 接口包装 Iterator,并在 iterator() 方法中进行循环检测。如果不做防护,程序将抛出 OutOfMemoryError 或 CPU 占用率飙升。


















