java iterator 遍历备忘录模式的核心做法是:在 originator(发起人)内部定义一个实现了 iterator 接口的私有类,将 memento(备忘录)中的状态数据暴露给该迭代器。调用者通过 getiterator() 方法获取迭代器实例,即可在不破坏封装性的前提下,按顺序访问历史状态或当前状态。

如何设计支持迭代的备忘录结构
要实现可遍历的备忘录,关键在于将“保存状态”与“遍历状态”解耦。通常的做法是让 Memento 对象持有一个列表(如 List<state></state>),而 Originator 负责维护这个列表并生成迭代器。这样,迭代器可以直接读取备忘录中的数据,而不需要暴露具体的状态字段。

import java.util.*;
// 1. 定义状态接口
interface State {
String getValue();
}
// 2. 具体状态实现
class ConcreteState implements State {
private final String value;
public ConcreteState(String value) { this.value = value; }
public String getValue() { return value; }
}
// 3. 备忘录:持有历史状态列表
class Memento {
private final List<State> history;
public Memento(List<State> history) { this.history = history; }
public List<State> getHistory() { return new ArrayList<>(history); }
}
// 4. 发起人:包含迭代器逻辑
class Originator {
private List<State> states = new ArrayList<>();
// 创建备忘录
public Memento save() {
return new Memento(states);
}
// 恢复状态
public void restore(Memento memento) {
this.states = memento.getHistory();
}
// 添加新状态
public void addState(State state) {
states.add(state);
}
// 核心:返回自定义迭代器
public Iterator<State> getIterator() {
return states.iterator();
}
}上述代码展示了最基础的实现。当调用 save() 时,会将当前的 states 列表快照存入 Memento。当外部需要遍历时,直接调用 getIterator() 即可获得一个标准的 Java Iterator。这种方式保证了 Memento 的内部结构对调用者是透明的,调用者只能看到 State 对象,无法修改其内部值。
立即学习“Java免费学习笔记(深入)”;
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
如何在迭代过程中处理状态快照
在实际使用中,往往需要在遍历历史状态的同时,确保每个状态都是独立的快照,避免引用共享导致的数据污染。如果在 Memento 中直接返回原始列表的迭代器,且状态对象是可变的,那么遍历过程中的任何修改都会影响原始数据。因此,必须在 Memento 构建时进行深拷贝,或者在迭代器层面提供只读视图。

// 改进版:确保状态不可变或深拷贝
class ImmutableState implements State {
private final String value;
public ImmutableState(String value) { this.value = value; }
public String getValue() { return value; }
}
// 在 Originator 中使用时
public class SafeOriginator {
private List<ImmutableState> states = new ArrayList<>();
public Memento save() {
// 深拷贝策略:创建新的列表和新的状态实例
List<ImmutableState> copy = new ArrayList<>();
for (ImmutableState s : states) {
copy.add(new ImmutableState(s.getValue()));
}
return new Memento(copy);
}
public Iterator<State> getIterator() {
// 返回不可变列表的迭代器,防止外部移除元素
return Collections.unmodifiableList(states).iterator();
}
}通过引入不可变状态(ImmutableState)和使用 Collections.unmodifiableList,可以彻底杜绝遍历时的副作用。此时,getIterator() 返回的迭代器不仅允许遍历,还禁止了 remove() 操作,确保了内存模型的一致性。这种设计特别适用于需要回溯历史记录的场景,比如文本编辑器的撤销功能,用户可以在历史版本间穿梭查看,但不会意外篡改某个历史版本的文本内容。
基于程序中某个输入、条件或结果的具体问题
如果程序中输入的状态数量极大,例如超过百万级,直接使用 ArrayList 存储所有历史状态会导致内存溢出。此时,应改用链表结构或分页加载策略。在迭代器实现上,可以使用懒加载(Lazy Loading)方式,仅在迭代到某一步时才从磁盘或数据库加载对应的状态对象,从而将内存占用从 O(N) 降低到 O(1)。

















