Practice
Solution
Step 1: Understand the problem requirement
The goal is to create a new object where nested mutable fields are independent, so changes in the copy do not affect the original.Step 2: Evaluate approaches
Manual shallow copy (A) shares nested references, causing side effects. Greedy selective copying (B) is not a standard approach and risks missing nested objects. JSON serialization (D) can lose methods and fail on special objects. Recursive deep copy (C) ensures all nested objects are duplicated, preserving independence.Final Answer:
Option D -> Option DQuick Check:
Deep copy duplicates nested objects -> no shared references [OK]
- Assuming shallow copy suffices for nested mutable fields
Solution
Step 1: Embedding snakes/ladders inside Board
This approach simplifies initial design but tightly couples Board to these elements.Step 2: Impact on extensibility
Tightly coupled design makes it harder to add new board elements (e.g., portals, traps) without modifying Board.Step 3: Modeling as separate entities
Allows easy extension by adding new element types without changing Board internals.Step 4: Complexity and memory considerations
Separate entities add minimal overhead; runtime complexity impact is negligible.Final Answer:
Option B -> Option BQuick Check:
Trade-off is between simplicity and extensibility, not runtime complexity or memory bloat.
- Thinking separate entities cause big runtime overhead
- Believing embedding improves encapsulation and immutability
- Assuming separate entities cause memory bloat
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: Identify trade-offs of OCP
Strict adherence often results in many small subclasses, increasing complexity.Step 2: Why other options are false
It forces all changes to be made in a single base class, increasing risk of bugs is opposite to OCP's goal; changes are made via extension, not base modification. It eliminates the need for interfaces or abstract classes, simplifying design is false because OCP relies on abstractions like interfaces. It guarantees zero runtime overhead due to polymorphism is incorrect; polymorphism can introduce slight runtime overhead.Final Answer:
Option B -> Option BQuick Check:
Class explosion is a known practical downside of OCP.
- Thinking OCP centralizes changes in base classes
- Believing OCP removes need for abstractions
- Assuming polymorphism has no runtime cost
Solution
Step 1: Understand reuse requirement
Reusing parts means the Builder should keep built parts cached and reuse them instead of rebuilding.Step 2: Evaluate options
Cache built parts inside the Builder and reuse them when building new objects. caches parts inside Builder, enabling reuse. Modify the Builder to reset the product after each get_result call to avoid reuse. resets product, preventing reuse. Abstract Factory and Factory do not handle stepwise reuse well.Final Answer:
Option C -> Option CQuick Check:
Caching parts in Builder enables reuse efficiently [OK]
- Resetting product disables reuse
- Confusing Abstract Factory with Builder reuse
