访问者模式
Visitor — 在不修改类的前提下,为其添加新的操作
一句话理解
把操作从数据结构中抽离出来,放到独立的"访问者"中。数据结构不变,想加新操作就加新访问者。
解决什么问题
- 数据结构稳定,但需要频繁添加新的操作
- 不想每次加操作都去修改数据类
怎么写
以"文件系统分析"为例:文件结构固定,但分析方式多种多样(统计大小、列出名称等)。
// 访问者接口
public interface FileVisitor {
void visit(TextFile file);
void visit(ImageFile file);
}
// 元素接口
public interface FileElement {
void accept(FileVisitor visitor);
}
// 具体元素
public class TextFile implements FileElement {
private final String name;
private final int lines;
public TextFile(String name, int lines) { this.name = name; this.lines = lines; }
public String getName() { return name; }
public int getLines() { return lines; }
public void accept(FileVisitor visitor) { visitor.visit(this); }
}
public class ImageFile implements FileElement {
private final String name;
private final long sizeKB;
public ImageFile(String name, long sizeKB) { this.name = name; this.sizeKB = sizeKB; }
public String getName() { return name; }
public long getSizeKB() { return sizeKB; }
public void accept(FileVisitor visitor) { visitor.visit(this); }
}
// 具体访问者:统计信息
public class SummaryVisitor implements FileVisitor {
private int totalLines = 0;
private long totalSize = 0;
public void visit(TextFile f) { totalLines += f.getLines(); }
public void visit(ImageFile f) { totalSize += f.getSizeKB(); }
public void report() {
System.out.println("文本总行数: " + totalLines);
System.out.println("图片总大小: " + totalSize + "KB");
}
}List<FileElement> files = List.of(
new TextFile("readme.md", 100),
new TextFile("code.java", 500),
new ImageFile("logo.png", 200)
);
SummaryVisitor visitor = new SummaryVisitor();
files.forEach(f -> f.accept(visitor));
visitor.report();
// 文本总行数: 600
// 图片总大小: 200KB使用场景
- 编译器中的 AST(抽象语法树)遍历
- 文档导出(同一份文档 → HTML/PDF/Markdown)
- 代码分析工具(统计行数、复杂度、依赖关系)
- Java 的
FileVisitor(NIO Files.walkFileTree)