A canonical example of the Composite pattern is modeling a file system, where both files and folders are treated as nodes implementing the same interface. This lets operations like search or delete work identically whether they're applied to a single file or an entire directory tree.
Key Points: • A FileSystemNode interface declares shared operations such as getSize() or delete(). • File is a leaf node with no children, implementing the operations directly. • Folder is a composite node holding a list of child FileSystemNode objects and delegating to them recursively. • Calling delete() on a Folder recursively deletes every file and subfolder beneath it. • The client code never needs to know whether it's holding a File or a Folder.
Example: Calling folder.getSize() on a top-level directory recursively sums the size of every nested file and folder beneath it, exactly as if you called file.getSize() on a single file.
Code Example:
interface FileSystemNode {
int getSize();
}
class FileNode implements FileSystemNode {
private int size;
FileNode(int size) { this.size = size; }
public int getSize() { return size; }
}
class FolderNode implements FileSystemNode {
private List<FileSystemNode> children = new ArrayList<>();
public void add(FileSystemNode node) { children.add(node); }
public int getSize() {
int total = 0;
for (FileSystemNode child : children) {
total += child.getSize();
}
return total;
}
}Interview Tip: A concise interview answer is:
"The classic example is a file system: files are leaf nodes and folders are composite nodes that hold other files or folders, both implementing the same interface. Calling something like getSize() or delete() on a folder just recurses through its children, so the client never needs to special-case files versus folders."