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
Solution
Step 1: Check availability atomically
LoanManager must verify the book is available before granting loan to prevent race conditions.Step 2: Why not immediate update?
The system immediately updates the book status to 'borrowed' for the requesting user without checking current loans risks data inconsistency by ignoring current loan state.Step 3: Why not User updates first?
The User class updates its borrowed books list first, then the system verifies availability asynchronously breaks transactional integrity and can cause stale or conflicting states.Step 4: Why not queue without feedback?
The Library class queues the request and processes it after the current loan expires without immediate feedback delays user feedback and complicates user experience; immediate denial is standard.Final Answer:
Option D -> Option DQuick Check:
Atomic availability check and denial maintain consistency and user clarity.
- Assuming immediate state update without checks
- Updating user state before system validation
- Delaying feedback by queuing without immediate response
k decorators on a core object using the Decorator Pattern with dynamic behavior injection?Solution
Step 1: Identify call chain length
Each decorator's cost() calls the wrapped object's cost(), forming a chain of length k.Step 2: Calculate total calls
Cost computation requires traversing all k decorators once, so time complexity is O(k).Final Answer:
Option B -> Option BQuick Check:
Each decorator adds constant work, total linear in k [OK]
- Assuming O(1) because cost is a simple addition
- Mistaking recursive calls as quadratic
Solution
Step 1: Understand strict LSP enforcement
Strict LSP means subclasses cannot alter behavior or method contracts in incompatible ways.Step 2: Analyze trade-offs
This can restrict subclass implementations, making designs rigid and limiting specialization.Step 3: Evaluate options
It can lead to overly rigid designs that prevent useful specialization. correctly identifies rigidity as a trade-off. It always improves code flexibility and reduces bugs without downsides. is false; strict LSP can reduce flexibility. It allows subclasses to freely change method signatures for optimization. is incorrect; method signatures must respect variance rules. It eliminates the need for interface segregation. is false; interface segregation addresses different concerns.Final Answer:
Option A -> Option AQuick Check:
Strict LSP can constrain subclass design choices.
- Believing strict LSP has no downsides
- Confusing LSP with interface segregation
- Assuming method signatures can be freely changed
Solution
Step 1: Analyze statement A
OCP does not forbid all modifications; it encourages minimizing changes to stable, tested code but allows modifications when necessary.Step 2: Validate other statements
Statements B, C, and D correctly describe OCP's goals and mechanisms.Step 3: Why A is incorrect
Absolute prohibition of modification is impractical; OCP is about minimizing and isolating changes.Final Answer:
Option A -> Option AQuick Check:
OCP is about minimizing, not forbidding, modifications.
- Interpreting OCP as no code changes ever allowed
- Ignoring the role of abstraction in OCP
- Underestimating OCP's impact on bug reduction
