Practice
Solution
Step 1: Understand Single Responsibility Principle
Tracking loans and returns involves managing transactions and state changes, which is best encapsulated in a dedicated LoanManager to avoid bloating Book or User classes.Step 2: Why not Book class?
Embedding availability logic in Book violates SRP and complicates concurrency handling.Step 3: Why not User class?
User should track borrowed books but not manage loan state transitions globally.Step 4: Why not Library class?
Library manages collections but delegating loan logic to a specialized manager improves modularity and concurrency control.Final Answer:
Option A -> Option AQuick Check:
LoanManager centralizes loan logic, enabling better consistency and easier concurrency handling.
- Putting loan logic inside Book class
- Letting User class handle global loan state
- Overloading Library class with transaction details
Solution
Step 1: Identify encapsulation flow
Private fields cannot be accessed directly; setters provide controlled access.Step 2: Follow setter method process
Setter receives input, validates it, updates the private field, then returns control.Step 3: Analyze incorrect options
The client directly modifies the private field without any method call violates data hiding. The getter method is called first to check the current value before updating misuses getter before setter. The private field is copied to a public variable which the client modifies breaks encapsulation by exposing private data.Final Answer:
Option C -> Option CQuick Check:
Setters control updates with validation, preserving encapsulation.
- Assuming direct field access through setters
- Confusing getter and setter roles
- Thinking private data is copied out for modification
if-else statements to handle different payment methods like credit card, UPI, and net banking. The system needs to be extended frequently with new payment methods without modifying existing code. Which design approach best addresses this requirement?Solution
Step 1: Understand the problem of frequent extension
The system requires adding new payment methods without modifying existing code, which violates the open-closed principle if usingif-elsechains.Step 2: Identify the design pattern that encapsulates behaviors
The strategy pattern encapsulates each payment method in its own class implementing a common interface, allowing easy extension by adding new classes without changing existing code.Final Answer:
Option B -> Option BQuick Check:
Strategy pattern replaces conditionals with polymorphism [OK]
- Thinking recursion or greedy algorithms solve extensibility here
Solution
Step 1: Understand double-checked locking behavior
Synchronization occurs only during the first initialization; subsequent calls skip locking due to the volatile check.Step 2: Analyze time complexity after initialization
After initialization, the instance is returned immediately without synchronization, so access is constant time.Final Answer:
Option A -> Option AQuick Check:
Locking overhead is avoided after first init, so O(1) access [OK]
- Assuming synchronization on every call
- Confusing locking cost with algorithmic complexity
- Overestimating contention impact
Solution
Step 1: Understand the new requirement
Multiple instances allowed but capped; lazy initialization and thread safety still required.Step 2: Evaluate options
Enum constants are fixed and static, not lazy. Synchronizing entire method causes performance issues and reusing last instance breaks fairness. Eager initialization wastes resources if instances are unused. A thread-safe pool lazily creating instances up to max fits all requirements.Final Answer:
Option A -> Option AQuick Check:
Thread-safe lazy pool creation matches new constraints [OK]
- Using enum for multiple instances
- Synchronizing entire method unnecessarily
- Eagerly creating all instances wasting resources
