What if you could treat a single file and a whole folder the exact same way in your code?
Why Composite pattern in LLD? - Purpose & Use Cases
Imagine you have a folder with files and subfolders, and you want to perform actions like opening or deleting on them. Doing this manually means writing separate code for files and folders, and then more code to handle folders inside folders, which quickly becomes messy.
Manually handling each file and folder type separately leads to repetitive code and lots of special cases. It's easy to forget to handle a new folder inside a folder, causing bugs. The code becomes hard to read and maintain as the structure grows.
The Composite pattern treats individual objects and groups of objects uniformly. It lets you write one interface for both files and folders, so you can perform actions on any item without worrying about its type. This simplifies code and scales naturally.
if item is file: open_file(item) else if item is folder: for child in item.children: open(child)
item.open() # Works for both file and folder
It enables building flexible, tree-like structures where clients can treat individual and grouped objects the same way, making complex hierarchies easy to manage.
File explorers use the Composite pattern to let users open, move, or delete files and folders seamlessly, no matter how deeply nested they are.
Composite pattern unifies handling of single and grouped objects.
Reduces code duplication and complexity in hierarchical structures.
Makes adding new components easier without changing client code.
Practice
Composite pattern in system design?Solution
Step 1: Understand the Composite pattern goal
The Composite pattern allows treating individual objects and groups of objects the same way.Step 2: Compare with other design patterns
Other options describe different patterns: Singleton (A), Iterator (D), Bridge (B).Final Answer:
To treat individual objects and compositions of objects uniformly -> Option DQuick Check:
Composite pattern = treat objects uniformly [OK]
- Confusing Composite with Singleton pattern
- Thinking Composite only manages single objects
- Mixing Composite with Iterator or Bridge patterns
Solution
Step 1: Identify typical Composite interface methods
Composite pattern usually includes methods like add(), remove(), and getChild() to manage children.Step 2: Match method signature to Composite pattern
Onlyvoid add(Component component);fits the pattern's purpose of managing child components.Final Answer:
void add(Component component); -> Option BQuick Check:
Composite interface method = add(Component) [OK]
- Choosing unrelated method signatures
- Confusing standard Object methods with Composite methods
- Ignoring the need to manage child components
class Component:
def operation(self):
pass
class Leaf(Component):
def operation(self):
return "Leaf"
class Composite(Component):
def __init__(self):
self.children = []
def add(self, component):
self.children.append(component)
def operation(self):
results = []
for child in self.children:
results.append(child.operation())
return "Composite(" + ", ".join(results) + ")"
leaf1 = Leaf()
leaf2 = Leaf()
composite = Composite()
composite.add(leaf1)
composite.add(leaf2)
print(composite.operation())Solution
Step 1: Understand Leaf operation output
Each Leaf's operation returns the string "Leaf".Step 2: Understand Composite operation output
Composite calls operation on each child and joins results with commas inside "Composite(...)".Final Answer:
Composite(Leaf, Leaf) -> Option AQuick Check:
Composite operation = Composite(Leaf, Leaf) [OK]
- Expecting just 'Leaf' output
- Ignoring the Composite wrapper in output
- Confusing list join syntax
class Component:
def operation(self):
pass
class Leaf(Component):
def operation(self):
return "Leaf"
class Composite(Component):
def __init__(self):
self.children = []
def add(self, component):
self.children.append(component)
def operation(self):
results = []
for child in self.children:
child.operation()
return "Composite(" + ", ".join(results) + ")"
Solution
Step 1: Analyze operation method in Composite
The loop callschild.operation()but does not append results to the list.Step 2: Identify missing result collection
Without appending,resultsremains empty, causing incorrect output.Final Answer:
The operation method does not collect child results -> Option CQuick Check:
Missing append in loop = operation method error [OK]
- Ignoring missing append to results list
- Thinking add method type check is mandatory
- Assuming inheritance error without evidence
Solution
Step 1: Apply Composite pattern principle of uniformity
AddingcountVisible()to Component interface lets all nodes handle counting uniformly.Step 2: Implement counting in Leaf and Composite
Leaf returns 1 if visible, 0 otherwise; Composite sums counts from children.Final Answer:
Add a countVisible() method to the Component interface, implemented by Leaf and Composite classes -> Option AQuick Check:
Uniform method in Component = best Composite design [OK]
- Using external counters breaking encapsulation
- Counting only leaves ignoring composites
- Manual traversal outside object methods
Ready to prove it?
Pass the test and this pattern moves unknown
