What does SOLID stand for?
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
SOLID (in one sentence): what is it?
A set of OO design principles that help you build code that is easier to change, test, and extend without breaking existing behavior.
SRP: What is the Single Responsibility Principle?
A class/module should have one reason to change (i.e., one primary responsibility).
SRP: Common code smell that violates it?
“God” classes (e.g., OrderService that validates, calculates pricing, persists, sends emails, and logs).
SRP: Java refactor example (high-level)
Split responsibilities:
- OrderValidator
- PricingService
- OrderRepository
- EmailNotifierOrderService orchestrates.
OCP: What is the Open/Closed Principle?
Software entities should be open for extension but closed for modification (add behavior without editing existing code paths).
OCP: Typical Java technique to achieve it?
Program to interfaces + polymorphism.
Example: DiscountPolicy interface with implementations; add new policies without changing pricing code.
OCP: When is a switch on type/code a red flag?
When every new feature requires editing the switch (violates OCP). Prefer polymorphism/registry when the set of behaviors grows.
LSP: What is the Liskov Substitution Principle?
Subtypes must be substitutable for their base types without altering correctness.
(Clients using the base type shouldn’t need special-case logic.)
LSP: Rectangle/Square classic issue (why it breaks)?
If Square inherits Rectangle but setters enforce equal sides, code that assumes independent width/height can fail. Prefer composition or redesign the abstraction.
LSP: Quick checklist for a subclass
ISP: What is the Interface Segregation Principle?
Clients should not be forced to depend on methods they do not use.
Prefer several small interfaces over one “fat” interface.
ISP: Java example
Instead of IMultiFunctionDevice { print(); scan(); fax(); }, use:Printer, Scanner, Fax interfaces.
Classes implement only what they support.
DIP: What is the Dependency Inversion Principle?
High-level modules should not depend on low-level modules; both should depend on abstractions.
Abstractions should not depend on details; details depend on abstractions.
DIP: Java practice to implement it
Use constructor injection with interfaces.
Example: OrderService(OrderRepository repo, PaymentGateway gateway).
Avoid new ConcreteRepo() inside business logic.
DIP vs DI: what’s the difference?
DIP is a design principle.
DI (Dependency Injection) is a technique/pattern to supply dependencies (often used to achieve DIP).
Cohesion vs coupling (why SOLID cares)
High cohesion: related responsibilities together.
Low coupling: fewer/looser dependencies.
SOLID tends to increase cohesion and reduce coupling.
Design Pattern: Singleton — intent
Intent: Ensure a class has only one instance and provide a global access point.
Design Pattern: Singleton — Java implementation notes / pitfalls
Java notes: Prefer enum Singleton { INSTANCE; } for serialization safety.
Avoid using Singleton as a “global variable” (hurts testability).
Design Pattern: Factory Method — intent
Intent: Define an interface for creating an object, but let subclasses decide which class to instantiate.
Design Pattern: Factory Method — Java implementation notes / pitfalls
Java notes: Often a static factory (of, valueOf) or overridable create() method.
Use when creation varies by subclass/environment.
Design Pattern: Abstract Factory — intent
Intent: Provide an interface for creating families of related objects without specifying concrete classes.
Design Pattern: Abstract Factory — Java implementation notes / pitfalls
Java notes: Useful for UI/toolkit families, DB drivers, or platform-specific components.
Often pairs with DI: inject a factory for a family.
Design Pattern: Builder — intent
Intent: Separate construction of a complex object from its representation; build step-by-step.