Top Interview Questions
Design Patterns are reusable solutions to common problems that occur in software design. They are not finished code or ready-made libraries, but rather proven templates or blueprints that developers can adapt to solve recurring design challenges in a consistent and efficient way.
Think of design patterns as best practices developed over time by experienced software engineers—they help you write code that is flexible, reusable, maintainable, and easy to understand.
In software engineering, developers often encounter similar problems when designing systems. Instead of reinventing solutions each time, design patterns provide standardized approaches to solving these problems.
A design pattern typically includes:
A problem (what issue it solves)
A solution (how it solves it)
The context (when to use it)
The consequences (pros and cons)
They are especially important in object-oriented programming (OOP), where managing relationships between classes and objects is crucial.
Design patterns became widely popular after the publication of the book Design Patterns: Elements of Reusable Object-Oriented Software by four authors known as the Gang of Four (GoF):
Erich Gamma
Richard Helm
Ralph Johnson
John Vlissides
This book introduced 23 classic design patterns that are still widely used today.
Design patterns play a critical role in software development:
They provide tried-and-tested solutions that can be reused across projects.
Code written using patterns is easier to understand, modify, and extend.
Patterns help build systems that can grow without major redesign.
Developers can communicate ideas quickly using common pattern names like “Singleton” or “Factory.”
They encapsulate years of experience and proven techniques.
Design patterns are broadly divided into three categories:
These patterns deal with object creation mechanisms, making the system more flexible and reusable.
Ensures that a class has only one instance and provides a global access point.
Use Case: Logging systems, configuration settings
Defines an interface for creating objects but lets subclasses decide which class to instantiate.
Use Case: Creating objects without specifying exact classes
Provides an interface for creating families of related objects.
Use Case: UI frameworks supporting multiple themes
Separates the construction of a complex object from its representation.
Use Case: Building complex objects step by step (e.g., constructing a house or a car)
Creates new objects by copying an existing object.
Use Case: When object creation is expensive
These patterns deal with object composition and relationships between classes.
Allows incompatible interfaces to work together.
Use Case: Integrating new systems with legacy code
Separates abstraction from implementation so they can vary independently.
Treats individual objects and groups of objects uniformly.
Use Case: File systems (files and folders)
Adds new functionality to an object dynamically.
Use Case: Adding features without modifying existing code
Provides a simplified interface to a complex system.
Use Case: Simplifying APIs
Provides a placeholder or surrogate for another object.
Use Case: Access control, lazy loading
These patterns focus on communication between objects.
Defines a one-to-many relationship where changes in one object notify others.
Use Case: Event systems, notifications
Defines a family of algorithms and makes them interchangeable.
Use Case: Payment methods, sorting algorithms
Encapsulates a request as an object.
Use Case: Undo/redo functionality
Allows an object to change behavior when its state changes.
Passes a request along a chain of handlers.
Reduces direct communication between objects by introducing a mediator.
Design patterns can be compared to architectural blueprints.
For example:
A Singleton is like a government office—only one exists.
A Factory is like a manufacturing unit producing different products.
An Observer is like a subscription service where users get updates automatically.
Imagine you are building a notification system.
Instead of writing:
EmailNotification
SMSNotification
PushNotification
You create a factory that returns the correct object based on input.
This way:
You don’t need to change existing code when adding new types
You follow the Open/Closed Principle
Design patterns often work hand-in-hand with SOLID principles, which are guidelines for writing clean and maintainable code.
For example:
Singleton supports controlled access
Strategy follows the Open/Closed Principle
Observer supports loose coupling
Proven solutions reduce risk
Improve code readability
Encourage best practices
Speed up development
Promote loose coupling
Can add unnecessary complexity if overused
Not always needed for small projects
Requires understanding to apply correctly
Use design patterns when:
You encounter recurring design problems
You need scalable and maintainable solutions
You want to follow best practices
Avoid using them:
For simple problems
When they make code harder to understand
Design patterns are used in:
Web development frameworks
Mobile applications
Enterprise systems
Game development
Many modern frameworks internally use design patterns:
MVC (Model-View-Controller)
Dependency Injection
Event-driven architectures
Understand the problem before choosing a pattern
Don’t force a pattern where it’s not needed
Keep code simple and readable
Combine patterns when necessary
Design patterns are essential tools for software developers. They provide reusable, scalable, and efficient solutions to common design problems. By understanding and applying these patterns, developers can build systems that are not only functional but also elegant and maintainable.
Mastering design patterns takes time and practice, but once learned, they significantly improve your ability to design robust and flexible software systems.
Answer:
Design Patterns are reusable solutions to common software design problems.
They are:
Not code, but templates
Proven best practices
Language-independent
π Example: Singleton ensures only one object exists.
Answer:
Design patterns were popularized by the “Gang of Four (GoF)”:
Erich Gamma
Richard Helm
Ralph Johnson
John Vlissides
Answer:
Improve code reusability
Make code maintainable
Provide standard solutions
Improve communication among developers
Answer:
Creational → Object creation
Structural → Class/object composition
Behavioral → Object interaction
Answer:
| Design Pattern | Algorithm |
|---|---|
| Structure of code | Step-by-step solution |
| Reusable design | Problem-solving logic |
| High-level | Low-level |
Answer:
Ensures only one instance of a class exists.
Logger
Database connection
class Singleton:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
Answer:
Controlled access
Saves memory
Global access point
Answer:
Hard to test
Global state issues
Tight coupling
Answer:
Creates objects without exposing creation logic.
ShapeFactory.getShape("Circle")
Answer:
Constructor → Direct object creation
Factory → Encapsulates creation logic
Answer:
Creates families of related objects.
π Example: UI components for Windows/Mac
Answer:
Factory → One product
Abstract Factory → Multiple related products
Answer:
Used to construct complex objects step-by-step.
π Example: Building a house or meal
Answer:
Creates objects by cloning existing ones.
π Faster than creating from scratch
Answer:
Converts one interface into another.
π Example: Charger adapter
Answer:
Adds new functionality without modifying existing code.
π Example: Adding toppings to pizza
Answer:
Decorator → Runtime flexibility
Inheritance → Compile-time
Answer:
Provides a simplified interface to complex systems.
π Example: One API to call multiple services
Answer:
Acts as a placeholder or controller for another object.
π Example: Lazy loading images
Answer:
Treats individual and group objects uniformly.
π Example: File system (files + folders)
Answer:
Separates abstraction from implementation.
π Helps independent development
Answer:
Reduces memory usage by sharing objects.
π Example: Text editor characters
Answer:
One object notifies multiple observers.
π Example: YouTube subscribers
Answer:
Encapsulates interchangeable algorithms.
π Example: Payment methods
Answer:
Strategy → Clean and extensible
If-else → Hard to maintain
Answer:
Encapsulates request as an object.
π Example: Remote control
Answer:
Changes behavior when state changes.
π Example: Traffic light
Answer:
Defines skeleton of algorithm.
π Subclasses override steps
Answer:
Provides a way to access elements sequentially.
Answer:
Centralizes communication between objects.
Answer:
Passes request along chain until handled.
π Example: Approval system
Answer:
Saves object state for rollback.
π Example: Undo feature
Answer:
Evaluates language grammar.
Answer:
Adds new operations without modifying classes.
Answer:
Singleton → Single logger instance
Answer:
Strategy → Multiple payment methods
Answer:
Observer → Notify multiple users
Answer:
Abstract Factory
Answer:
Memento
Answer:
Prototype
Answer:
Facade
Answer:
Decorator
When asked about a pattern:
π Follow this structure:
Definition
Real-world example
Use case
Pros/cons
| Pattern | Use Case |
|---|---|
| Singleton | One instance |
| Factory | Object creation |
| Builder | Complex objects |
| Adapter | Compatibility |
| Observer | Notifications |
| Strategy | Multiple algorithms |
Don’t memorize blindly—understand use cases
Always give real-world analogy
Focus on 5–7 most common patterns deeply
Practice explaining in simple words
The Singleton Pattern ensures a class has only one instance and provides a global access point.
Logging systems
Configuration managers
Connection pools
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
β Hard to test (global state)
β Breaks SRP
β Controlled access
Hidden dependencies
Difficult unit testing
Concurrency issues (if poorly implemented)
Tight coupling
π Better alternative: Dependency Injection
The Factory Method Pattern defines an interface for object creation but lets subclasses decide the instantiation.
interface Shape {
void draw();
}
class Circle implements Shape {}
class Square implements Shape {}
abstract class ShapeFactory {
abstract Shape createShape();
}
When object creation logic is complex
| Feature | Factory Method | Abstract Factory |
|---|---|---|
| Scope | Single object | Family of objects |
| Complexity | Low | High |
| Example | Shape | UI toolkit |
π Abstract Factory Pattern creates related objects (e.g., buttons + checkboxes for Windows/Mac)
The Builder Pattern constructs complex objects step-by-step.
User user = new User.Builder()
.setName("John")
.setAge(30)
.build();
Many optional parameters
Constructor → messy with many params
Builder → readable, flexible
The Prototype Pattern creates objects by cloning existing ones.
Expensive object creation
Copying configurations
Shallow → references copied
Deep → full object cloned
Complex object graphs
Circular dependencies
The Adapter Pattern converts one interface into another.
Integrating legacy systems
| Adapter | Facade |
|---|---|
| Converts interface | Simplifies interface |
| Focus on compatibility | Focus on usability |
π Facade Pattern
The Decorator Pattern adds behavior dynamically.
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
Decorator → runtime flexibility
Inheritance → compile-time
The Proxy Pattern controls access to an object.
Virtual proxy
Security proxy
Caching proxy
Proxy → control access
Decorator → add behavior
The Composite Pattern treats individual and group objects uniformly.
File system (file + folder)
The Bridge Pattern decouples abstraction from implementation.
Multiple dimensions of variation
The Flyweight Pattern reduces memory by sharing objects.
Text editors (characters reuse)
Complex logic
Hard debugging
The Observer Pattern defines one-to-many dependency.
Event systems
UI updates
Observer → tight coupling
Pub-Sub → loosely coupled (via broker)
The Strategy Pattern defines interchangeable algorithms.
interface PaymentStrategy {}
class CreditCard implements PaymentStrategy {}
class UPI implements PaymentStrategy {}
Strategy → interchangeable algorithms
State → object behavior changes internally
The State Pattern changes behavior based on state.
The Command Pattern encapsulates a request as an object.
Undo/redo
Task queues
The Chain of Responsibility Pattern passes request along a chain.
The Template Method Pattern defines skeleton of algorithm.
The Iterator Pattern provides sequential access.
The Mediator Pattern reduces direct dependencies.
The Memento Pattern captures object state.
The Interpreter Pattern evaluates expressions.
The Visitor Pattern separates operations from object structure.
Singleton (default beans)
Proxy (AOP)
Factory
Singleton
Factory
Decoupling
Reusability
Flexibility
God object
Overuse of Singleton
Tight coupling
Over-engineering
Simple problems
Patterns → solutions
Principles → guidelines (SOLID)
Use:
Strategy → payment methods
Factory → create payment objects
Observer → notifications
Circuit Breaker
API Gateway
Saga pattern
Identify problem
Look for variability
Choose pattern that reduces coupling
At 4+ years, interviewers expect:
Not just definitions β
But why, when, trade-offs, real examples β