Interface Segregation & Dependency Inversion - Fat Interfaces & IoC - Watch the Algorithm Execute, Step by Step
Watching this step-by-step visualization helps you understand how SOLID principles improve design by reducing coupling and increasing flexibility, which is hard to grasp from code alone.
Step 1/10
·Active fill★Answer cell
Shows a fat interface violating Interface Segregation Principle.
«interface»IMultiFunctionDevice
+print()
+scan()
+fax()
⚠ Clients depending on IMultiFunctionDevice must implement all methods, even if unused.
Demonstrates Interface Segregation Principle by splitting responsibilities.
«interface»IPrinter
+print()
«interface»IScanner
+scan()
«interface»IFax
+fax()
Shows class implementing a segregated interface.
«interface»IPrinter
+print()
Printer
+print()
Printer → IPrinter (1:1)
Another example of ISP applied to class design.
«interface»IScanner
+scan()
Scanner
+scan()
Scanner → IScanner (1:1)
Demonstrates Dependency Inversion and IoC by depending on interfaces and composing implementations.
✓ Fat interfaces force clients to depend on methods they don't use, violating Interface Segregation Principle.
This is hard to see from code alone because the problem is conceptual and relates to coupling, not syntax.
✓ Splitting interfaces into smaller, focused ones allows classes to implement only what they need, improving modularity.
Visualizing the interfaces and implementations side-by-side clarifies how responsibilities are separated.
✓ Dependency Inversion Principle and Inversion of Control decouple high-level modules from low-level modules by depending on abstractions and injecting dependencies.
Seeing the relationships and constructor injection visually makes the abstract DIP concept concrete.
Practice
(1/5)
1. In designing a parking lot system using OOP, which component is best suited to decide which type of parking spot (e.g., compact, large, handicapped) should be allocated to an incoming vehicle?
easy
A. The ParkingLot class, as it manages all spots and vehicles
B. The ParkingSpot class, since it represents the spot's characteristics
C. The Vehicle class, because it knows its own size and type
D. A Factory or Strategy pattern component that encapsulates the allocation logic
Solution
Step 1: Understand responsibilities
The Vehicle class only knows about itself, not allocation rules. The ParkingSpot class represents a spot but doesn't decide allocation. The ParkingLot manages overall state but delegating allocation logic to a dedicated component improves modularity.
Step 2: Recognize design pattern role
The Factory or Strategy pattern encapsulates allocation logic, allowing easy extension and modification without changing core classes.
Final Answer:
Option D -> Option D
Quick Check:
Allocation logic centralized -> easier to maintain and extend [OK]
Hint: Allocation logic belongs in a dedicated pattern component, not core entities [OK]
Common Mistakes:
Assigning allocation responsibility to Vehicle or ParkingSpot classes
Putting all logic inside ParkingLot class leading to tight coupling
2. You have a payment processing system that currently uses multiple 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?
easy
A. Use a brute force approach with nested if-else statements for each payment method.
B. Implement a strategy pattern where each payment method is encapsulated in its own class implementing a common interface.
C. Use a recursive function that selects payment methods based on input parameters.
D. Apply a greedy algorithm to select the payment method with the lowest processing fee.
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 using if-else chains.
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 B
Quick Check:
Strategy pattern replaces conditionals with polymorphism [OK]
Hint: Replacing conditionals with polymorphism enables easy extension [OK]
Common Mistakes:
Thinking recursion or greedy algorithms solve extensibility here
3. Which of the following is a common trade-off when using a Facade pattern in a large system?
medium
A. Facade can hide too much complexity, making it hard to access advanced features of subsystems
B. Facade increases coupling between client and subsystems by exposing detailed interfaces
C. Facade always adds significant runtime overhead due to extra method calls
D. Facade requires changing the underlying subsystem interfaces to work properly
Solution
Step 1: Recall Facade's purpose
Facade simplifies complex subsystems by providing a unified interface.
Step 2: Analyze trade-offs
While Facade simplifies usage, it can hide advanced features, limiting flexibility.
Step 3: Evaluate other options
A is incorrect because Facade reduces coupling by hiding subsystem details. C is incorrect; Facade's overhead is minimal. D is wrong; Facade does not require changing subsystems.
Final Answer:
Option A -> Option A
Hint: Facade hides complexity but may hide power
Common Mistakes:
Believing Facade increases coupling instead of reducing it
Assuming Facade adds heavy runtime overhead
Thinking Facade requires modifying subsystems
4. Which of the following statements about the Open/Closed Principle is INCORRECT?
medium
A. OCP means you should never modify existing code once it's written
B. OCP encourages designing modules that can be extended without changing their source code
C. Abstraction and polymorphism are key enablers of OCP
D. OCP helps reduce bugs by minimizing changes to tested code
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 A
Quick Check:
OCP is about minimizing, not forbidding, modifications.
Hint: OCP minimizes, but does not forbid, code changes [OK]
Common Mistakes:
Interpreting OCP as no code changes ever allowed
Ignoring the role of abstraction in OCP
Underestimating OCP's impact on bug reduction
5. What is a key limitation or trade-off of using method overloading extensively in a large codebase?
medium
A. It can cause ambiguity errors at compile time if parameter lists are too similar or implicit conversions apply
B. It increases runtime overhead due to dynamic dispatch and vtable lookups
C. It prevents subclasses from overriding methods with the same name
D. It requires all overloaded methods to have the same return type
Solution
Step 1: Understand overloading resolution
Overloading is resolved at compile time by matching method signatures.
Step 2: Identify ambiguity risk
If parameter lists are too similar or implicit conversions exist, the compiler may not decide which method to call, causing ambiguity errors.
Step 3: Analyze options
It can cause ambiguity errors at compile time if parameter lists are too similar or implicit conversions apply correctly identifies this compile-time ambiguity risk. It increases runtime overhead due to dynamic dispatch and vtable lookups incorrectly attributes runtime overhead to overloading (it's compile-time). It prevents subclasses from overriding methods with the same name is false; overloading does not prevent overriding. It requires all overloaded methods to have the same return type is false; return types can differ in overloading.
Final Answer:
Option A -> Option A
Quick Check:
Overloading can cause compile-time ambiguity, not runtime overhead or overriding restrictions.
Hint: Overloading ambiguity arises from similar parameter lists, not runtime costs
Common Mistakes:
Confusing overloading with overriding runtime costs