Structural patterns (Adapter, Decorator, Facade) in Software Engineering - Time & Space Complexity
We want to understand how the time it takes to use structural patterns changes as the size of the input or system grows.
Specifically, how do Adapter, Decorator, and Facade patterns affect the speed of a program?
Analyze the time complexity of the following example using the Decorator pattern.
class Component:
def operation(self):
return "Base"
class Decorator(Component):
def __init__(self, component):
self.component = component
def operation(self):
return f"Decorated({self.component.operation()})"
component = Component()
decorated = Decorator(component)
result = decorated.operation()
This code wraps a base component with a decorator that adds extra behavior when calling operation.
Look for repeated calls or loops that affect performance.
- Primary operation: Calling
operation()on the decorator which calls the wrapped component'soperation(). - How many times: Once per call, but can be nested if multiple decorators wrap each other.
As you add more decorators wrapping each other, each call to operation() triggers more calls inside.
| Number of Decorators (n) | Approx. Calls to operation() |
|---|---|
| 1 | 2 |
| 5 | 6 |
| 10 | 11 |
Pattern observation: The number of calls grows linearly with the number of decorators.
Time Complexity: O(n)
This means the time to complete the operation grows directly in proportion to how many decorators are added.
[X] Wrong: "Using these patterns does not affect performance at all."
[OK] Correct: Each added layer (like a decorator or adapter) adds extra method calls, which can increase execution time especially if many layers are stacked.
Understanding how structural patterns impact time helps you explain design choices clearly and shows you think about both design and performance.
What if we replaced the Decorator pattern with a Facade that calls multiple components internally? How would the time complexity change?
Practice
Solution
Step 1: Understand the role of Adapter pattern
The Adapter pattern converts the interface of one class into another interface clients expect, enabling incompatible interfaces to work together.Step 2: Compare with other patterns
Decorator adds features, Facade simplifies interfaces, Singleton controls instance creation. Only Adapter changes interfaces for compatibility.Final Answer:
Adapter -> Option BQuick Check:
Interface conversion = Adapter [OK]
- Confusing Decorator with Adapter
- Thinking Facade changes interfaces
- Mixing Singleton with structural patterns
Solution
Step 1: Identify the purpose of Decorator pattern
Decorator adds new features or responsibilities to objects dynamically without changing their structure.Step 2: Eliminate other options
It provides a simple interface to a complex system. describes Facade, It converts one interface to another. describes Adapter, It ensures a class has only one instance. describes Singleton pattern.Final Answer:
It adds new responsibilities to objects dynamically. -> Option CQuick Check:
Decorator = add features dynamically [OK]
- Mixing Decorator with Facade
- Confusing Adapter with Decorator
- Thinking Singleton is a structural pattern
Solution
Step 1: Understand Facade pattern role
Facade provides a simple unified interface to a set of interfaces in a subsystem, hiding complexity from the client.Step 2: Analyze options
The client can access all subsystem details directly. is wrong because Facade hides details. The client must adapt its interface to each subsystem. describes Adapter. The client can add new features to subsystems dynamically. describes Decorator.Final Answer:
The client interacts with a simple interface hiding complexity. -> Option AQuick Check:
Facade = simple interface to complex system [OK]
- Thinking Facade exposes all subsystem details
- Confusing Facade with Adapter or Decorator
- Assuming Facade adds features dynamically
Solution
Step 1: Identify Adapter pattern requirement
Adapter must implement the target interface expected by the client to convert calls properly.Step 2: Analyze failure cause
If the client still fails, likely the Adapter does not correctly implement or map the target interface methods.Final Answer:
The Adapter does not implement the target interface correctly. -> Option DQuick Check:
Adapter interface mismatch = implementation error [OK]
- Confusing Decorator or Facade with Adapter errors
- Assuming client code is always correct
- Ignoring interface method signatures
Solution
Step 1: Identify pattern for simplifying complex API
Facade provides a simple interface to a complex system, ideal for the legacy payment system.Step 2: Identify pattern for adding features without changing code
Decorator adds new responsibilities like logging dynamically without modifying original code.Step 3: Combine patterns logically
Use Facade to simplify the interface for clients, then wrap with Decorator to add logging features.Final Answer:
Facade to simplify interface and Decorator to add logging -> Option AQuick Check:
Simplify = Facade, Add features = Decorator [OK]
- Using Adapter to simplify interface instead of Facade
- Confusing roles of Adapter and Decorator
- Trying to add logging via Adapter
Ready to prove it?
Pass the test and this pattern moves unknown
