✓ Decorators wrap objects to add behavior dynamically without subclassing.
This is hard to see from code alone because the wrapping and delegation happen at runtime and are invisible in static class hierarchies.
✓ Method calls delegate through the decorator chain, accumulating behavior step-by-step.
Visualizing each call clarifies how each decorator contributes to the final result.
✓ Stacking multiple decorators composes complex behavior flexibly and transparently.
The trace shows how each decorator wraps the previous one, enabling modular extensions.
Practice
(1/5)
1. When a class implements an interface and also extends an abstract class, what is the sequence of abstraction enforcement and implementation that occurs during object instantiation?
easy
A. The abstract class constructor runs, but interface methods have no implementation to run.
B. Interface methods are implemented first, then the abstract class constructor runs.
C. The class must implement interface methods before the abstract class constructor runs.
D. The abstract class's constructor runs first, then interface methods are implemented by the class.
Solution
Step 1: Understand interface role
Interfaces declare methods but provide no implementation or constructors.
Step 2: Abstract class constructor behavior
Abstract class constructors run during instantiation to initialize shared state.
Step 3: Implementation of interface methods
The class implementing the interface provides method bodies; no constructor or code runs from interface itself.
Final Answer:
Option A -> Option A
Quick Check:
Interfaces define contracts only; abstract class constructors run during instantiation.
Hint: Interface methods have no constructor or implementation to run; abstract class constructors always run.
Common Mistakes:
Thinking interface methods have constructors or code to execute.
Believing interface implementation order affects constructor execution.
Confusing interface method implementation with constructor invocation.
2. You are designing a system that manages user accounts and sends notification emails. According to the Single Responsibility Principle, how should you organize these responsibilities?
easy
A. Separate user account management and email notification into different classes because each has a different reason to change.
B. Combine user account management and email notification in one class because they are related to users.
C. Put all user-related functionalities, including notifications, into a single class to reduce the number of classes.
D. Create one class for user management and embed email notification logic inside its methods to simplify interactions.
Solution
Step 1: Identify reasons to change
User account management changes when user data or authentication changes; email notifications change when messaging or delivery requirements change.
Step 2: Apply SRP
Since these reasons to change differ, they should be separated into different classes to avoid coupling unrelated changes.
Step 3: Evaluate other options
Options A, C, and D combine responsibilities, increasing coupling and reducing cohesion, violating SRP.
Final Answer:
Option A -> Option A
Quick Check:
Separate classes for distinct reasons to change -> SRP compliant.
Hint: One class, one reason to change.
Common Mistakes:
Assuming related domain means same responsibility.
Combining functionalities to reduce class count.
Embedding multiple responsibilities for convenience.
3. Which of the following statements about using inheritance to model different vehicle types in the parking lot system is INCORRECT?
medium
A. Inheritance allows sharing common vehicle attributes and behaviors in a base Vehicle class
B. Using inheritance for vehicle types can lead to rigid designs that are hard to extend with new types
C. Inheritance is always the best approach to add new vehicle types without modifying existing code
D. Polymorphism enables treating all vehicle types uniformly when allocating parking spots
Solution
Step 1: Review inheritance benefits
Inheritance supports code reuse and polymorphism for uniform handling.
Step 2: Recognize limitations
Inheritance hierarchies can become rigid and hard to extend, violating open-closed principle.
Step 3: Identify incorrect statement
Claiming inheritance is always best ignores alternatives like composition or interfaces that improve extensibility.
Final Answer:
Option C -> Option C
Quick Check:
Inheritance is not always best for extensibility [OK]
Hint: Inheritance can cause rigidity; prefer composition for extensibility [OK]
Common Mistakes:
Assuming inheritance is always the best design choice
Ignoring polymorphism benefits
4. What is the time complexity of notifying observers in the thread-safe observer pattern implementation where observers are stored in a dictionary mapping event types to sets of observers, and a snapshot list is created during notification?
medium
A. O(n) where n is total number of all observers across all event types
B. O(k) where k is the number of observers subscribed to the notified event type
C. O(k + n) where k is observers for event type and n is total observers
D. O(1) constant time due to hash set usage
Solution
Step 1: Identify the data structure and notification process
Observers are stored per event type in sets. Notification locks and copies only the observers for the specific event type.
Step 2: Analyze complexity of notify()
Notify creates a snapshot list of observers for the event type (size k) and iterates over it, so time is proportional to k, not total n.
Final Answer:
Option B -> Option B
Quick Check:
Notify cost depends only on observers for that event type [OK]
Hint: Notify complexity depends on observers for event type only [OK]
Common Mistakes:
Assuming notify iterates over all observers regardless of event type
5. In a legacy system, a class handles both business logic and logging. You want to refactor it following SRP, but the logging code is tightly intertwined with business logic. What is the best approach to refactor this while respecting SRP?
hard
A. Ignore SRP in this case because legacy code should not be refactored.
B. Leave logging inside the class because extracting it would break existing functionality and increase risk.
C. Merge business logic and logging into a utility class to centralize all cross-cutting concerns.
D. Extract logging into a separate class and replace logging calls with calls to this new class, even if it requires modifying many places.
Solution
Step 1: Identify responsibilities
Business logic and logging are separate reasons to change.
Step 2: Refactor strategy
Extract logging into its own class to isolate changes related to logging.
Step 3: Address tight coupling
Though intertwined, refactoring calls to the new logging class improves maintainability and respects SRP.
Step 4: Evaluate other options
Options B and D avoid refactoring, risking future issues; C increases coupling by merging unrelated concerns.
Final Answer:
Option D -> Option D
Quick Check:
Extract and isolate responsibilities even if it requires effort -> SRP compliance.
Hint: Separate concerns even if intertwined; refactor stepwise.
Common Mistakes:
Avoiding refactoring due to perceived risk.
Merging unrelated concerns for convenience.
Ignoring SRP in legacy code.
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.