Practice
Solution
Step 1: Understand the problem constraints
The problem requires adding features dynamically without subclass explosion.Step 2: Identify the design pattern that supports dynamic behavior wrapping
The Decorator Pattern uses composition to wrap objects and add behavior at runtime, avoiding subclassing for every combination.Final Answer:
Option D -> Option DQuick Check:
Dynamic wrapping via composition avoids subclass explosion [OK]
- Thinking subclassing is the only way to add features
- Confusing greedy algorithms with design patterns
print(house) after constructing a basic house with the Director?Solution
Step 1: Trace Director.construct_basic_house()
The Director calls build_walls() and build_roof() on the builder, adding "Walls" and "Roof" to the house parts.Step 2: Check the final house parts list
The house parts list contains ["Walls", "Roof"]. The pool is not added in this method.Final Answer:
Option A -> Option AQuick Check:
Only walls and roof are added in basic house construction [OK]
- Assuming pool is added by default
- Mixing order of parts
Solution
Step 1: Identify extension vs modification
Adding new payment methods should extend behavior without modifying existing classes.Step 2: Evaluate subclassing with common interface
Creating subclasses for each payment method allows extension by adding new classes, adhering to OCP.Step 3: Why other options fail
Adding new conditional branches inside the existing payment processor class for each new payment method and modifying existing code violate the 'closed for modification' part. Using global variables to switch between payment methods at runtime uses global state, which is unrelated and error-prone.Final Answer:
Option A -> Option AQuick Check:
Extension via polymorphism, no modification of existing code.
- Thinking adding conditionals is extension
- Believing modifying existing code is acceptable if tested
- Confusing global state management with OCP
Solution
Step 1: Understand backward compatibility
Adding a method directly to an interface breaks existing implementers if no default implementation exists.Step 2: Why converting to abstract class is problematic
Changing interface to abstract class breaks existing multiple inheritance and design contracts.Step 3: Using interface extension
Creating a new interface that extends the original preserves backward compatibility and allows gradual adoption.Step 4: Static methods in interfaces
Static methods do not affect instance method contracts and cannot replace instance methods.Final Answer:
Option B -> Option BQuick Check:
Extending interfaces is the safe way to evolve contracts without breaking clients.
- Assuming all implementers can update immediately.
- Thinking abstract classes can replace interfaces without impact.
- Confusing static methods with instance methods in interfaces.
Solution
Step 1: Analyze requirements
Control access by user roles -> Proxy fits. Add logging and caching without modifying code -> Decorator fits.Step 2: Evaluate options
A incorrectly assigns Facade for access control and Adapter for logging/caching. B misuses Adapter and Facade roles. C correctly assigns Proxy for access control and Decorator for adding behavior. D incorrectly uses Adapter for access control and Proxy for logging/caching.Final Answer:
Option C -> Option C
- Confusing Proxy and Decorator responsibilities
- Using Adapter or Facade for access control
- Assuming Proxy can add behavior like logging and caching
