java中结合iterator和原型模式,核心做法是让实现iterable接口的聚合类在迭代时,对内部存储的每个元素调用clone()方法生成浅拷贝或深拷贝副本,再返回这些副本的迭代器,从而保证遍历过程中外部修改不影响原始数据。具体实现需确保元素类正确覆写cloneable接口,并在聚合类的iterator()方法中实例化一个自定义iterator,该iterator持有原集合索引并逐个克隆元素。

PrototypeAggregate如何安全地暴露迭代器
当需要遍历一组原型对象且不希望暴露内部可变状态时,PrototypeAggregate应实现Iterable<t></t>接口,并在iterator()方法中创建一个新的迭代器实例。这个迭代器不直接返回原对象引用,而是通过调用对象的clone()方法来获取副本。这样做可以防止迭代期间外部代码意外修改原始原型对象的状态,同时也避免了并发修改异常的风险。关键在于迭代器内部维护一个指向原集合的索引,每次next()调用时执行克隆操作。

import java.util.*;
// 假设这是一个实现了Cloneable的原型对象
class PrototypeElement implements Cloneable {
String name;
int value;
public PrototypeElement(String name, int value) {
this.name = name;
this.value = value;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 浅拷贝
}
}
// 聚合类:管理原型元素并提供安全的迭代器
class PrototypeAggregate implements Iterable<PrototypeElement> {
private List<PrototypeElement> elements = new ArrayList<>();
public void addElement(PrototypeElement element) {
elements.add(element);
}
@Override
public Iterator<PrototypeElement> iterator() {
return new PrototypeIterator(elements);
}
// 内部迭代器类
private static class PrototypeIterator implements Iterator<PrototypeElement> {
private final List<PrototypeElement> source;
private int index = 0;
public PrototypeIterator(List<PrototypeElement> source) {
this.source = source;
}
@Override
public boolean hasNext() {
return index < source.size();
}
@Override
public PrototypeElement next() {
if (!hasNext()) throw new NoSuchElementException();
try {
// 关键步骤:克隆当前元素,返回副本而非原引用
return (PrototypeElement) source.get(index++).clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone not supported", e);
}
}
}
}
public class Main {
public static void main(String[] args) {
PrototypeAggregate aggregate = new PrototypeAggregate();
aggregate.addElement(new PrototypeElement("A", 1));
aggregate.addElement(new PrototypeElement("B", 2));
for (PrototypeElement elem : aggregate) {
System.out.println(elem.name + ": " + elem.value);
// 修改副本不会影响原始数据
elem.value = 99;
}
}
}
浅拷贝与深拷贝在迭代中的差异如何处理
在迭代原型对象时,如果原型对象包含引用类型字段(如数组、其他对象),默认的super.clone()仅进行浅拷贝,即共享内部引用。若业务要求迭代出的对象完全独立,必须手动实现深拷贝逻辑。例如,在clone()方法中重新实例化引用字段。这种差异直接影响迭代结果的安全性:浅拷贝下修改副本的内部引用对象会影响其他副本或原对象,而深拷贝则完全隔离。开发者应根据数据结构的复杂度选择拷贝策略,并在文档中明确说明。
立即学习“Java免费学习笔记(深入)”;

// 修改后的PrototypeElement以支持深拷贝
class DeepPrototypeElement implements Cloneable {
String name;
int[] data; // 引用类型字段
public DeepPrototypeElement(String name, int[] data) {
this.name = name;
this.data = data.clone(); // 构造时即深拷贝输入数组
}
@Override
protected Object clone() throws CloneNotSupportedException {
DeepPrototypeElement cloned = (DeepPrototypeElement) super.clone();
// 关键步骤:对引用字段进行深拷贝
cloned.data = this.data.clone();
return cloned;
}
}
迭代器抛出CloneNotSupportedException时程序如何响应
当PrototypeIterator在next()中调用clone()时,若元素类未正确实现Cloneable接口或未处理异常,将抛出CloneNotSupportedException。在实际代码中,我们将其包装为运行时异常RuntimeException并传播,导致程序终止。这是一种快速失败策略,适用于开发阶段发现配置错误。在生产环境中,更稳健的做法是捕获该异常并记录日志,或者提供一个回退机制(如返回null或跳过该元素),但需注意这可能会破坏迭代的一致性。因此,确保所有参与迭代的原型类都正确实现Cloneable是前置条件。


















