Chapter 18
Problem 14: Design a File System
The setup
"Design a file system (in-memory or persistent). Files and directories arranged hierarchically; standard operations: create, read, write, delete, list, move."
The Composite pattern
abstract class FileSystemNode {
String name;
Directory parent;
Instant createdAt, modifiedAt;
long size();
abstract boolean isDirectory();
}
class File extends FileSystemNode {
byte[] contents;
public long size() { return contents.length; }
public boolean isDirectory() { return false; }
}
class Directory extends FileSystemNode {
Map children = new HashMap<>();
public long size() {
return children.values().stream().mapToLong(FileSystemNode::size).sum();
}
public boolean isDirectory() { return true; }
}
Composite pattern: File and Directory both extend FileSystemNode; Directory holds a collection of FileSystemNodes (which may be Files or other Directories). Operations like "size" recurse naturally.
The FileSystem service
class FileSystem {
private Directory root = new Directory("/");
public File createFile(String path, byte[] contents) {
String[] parts = parsePath(path);
Directory dir = navigateTo(parts, true); // create intermediate dirs if needed
String filename = parts[parts.length - 1];
File f = new File(filename);
f.contents = contents;
dir.children.put(filename, f);
return f;
}
public List list(String path) {
Directory dir = navigateToDir(path);
return new ArrayList<>(dir.children.values());
}
// ... etc.
}
Takeaway
File systems are the textbook Composite pattern. Treating files and directories uniformly via a common interface makes tree operations clean. Real-world file systems add complexity (permissions, links, journaling) but the core design is this Composite.