Top Interview Questions
Design Patterns in Software Development
In software engineering, achieving code that is efficient, maintainable, and reusable is often a significant challenge. Over the years, experienced developers have encountered recurring problems and devised standardized solutions to address them effectively. These standardized solutions are referred to as design patterns. Design patterns are not finished pieces of code that can be copied and pasted; rather, they are templates or blueprints that provide a guide for solving common design problems in software development.
The concept of design patterns gained popularity with the seminal book “Design Patterns: Elements of Reusable Object-Oriented Software” by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, collectively known as the Gang of Four (GoF). The book classified design patterns into three main categories: Creational, Structural, and Behavioral patterns.
Creational patterns deal with object creation mechanisms. They provide ways to create objects in a manner suitable to the situation, without directly instantiating classes in the code. This improves flexibility and reduces coupling between classes. Common creational patterns include:
Singleton Pattern: Ensures that a class has only one instance and provides a global point of access to it. It is useful for resources like configuration settings or logging, where multiple instances could cause conflicts or resource waste.
Factory Method Pattern: Defines an interface for creating objects but allows subclasses to alter the type of objects that will be created. It is particularly useful when a class cannot anticipate the type of objects it needs to create.
Abstract Factory Pattern: Provides an interface to create families of related or dependent objects without specifying their concrete classes. This pattern is widely used in GUI frameworks to create platform-specific components.
Builder Pattern: Separates the construction of a complex object from its representation, allowing the same construction process to create different representations. It is often used in scenarios like building a document or constructing an HTML page.
Prototype Pattern: Creates new objects by copying an existing object, known as the prototype. This pattern is helpful when object creation is costly in terms of resources or time.
Structural patterns focus on how classes and objects are composed to form larger structures. They aim to simplify the design by identifying simple ways to realize relationships between entities. Common structural patterns include:
Adapter Pattern: Allows incompatible interfaces to work together by converting one interface into another expected by the client. For example, it can allow legacy code to interact with new systems.
Decorator Pattern: Dynamically adds behavior or responsibilities to an object without modifying its structure. This is particularly useful when you need flexible extensions for classes without altering their code.
Facade Pattern: Provides a simplified interface to a larger body of code, such as a complex subsystem. This pattern hides the complexities of the subsystem from clients.
Composite Pattern: Allows individual objects and compositions of objects to be treated uniformly. It is commonly used to represent hierarchical structures like trees.
Proxy Pattern: Provides a surrogate or placeholder for another object to control access to it, often for reasons like lazy initialization, access control, or logging.
Behavioral patterns focus on how objects interact and communicate with each other. They help define the patterns of communication between objects while keeping the code flexible and maintainable. Common behavioral patterns include:
Observer Pattern: Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified automatically. This pattern is commonly used in event handling systems and MVC frameworks.
Strategy Pattern: Defines a family of algorithms, encapsulates each one, and makes them interchangeable. This allows the algorithm to vary independently from the clients that use it.
Command Pattern: Encapsulates a request as an object, thereby allowing parameterization of clients with queues, requests, and operations. It is widely used in GUI buttons and undo operations.
Iterator Pattern: Provides a way to access elements of a collection sequentially without exposing its underlying representation. It helps decouple iteration logic from data structures.
State Pattern: Allows an object to alter its behavior when its internal state changes, making it appear as if the object changed its class. This pattern is helpful in implementing finite state machines.
Reusability: Design patterns provide proven solutions that can be reused across projects, reducing development time.
Maintainability: Patterns promote a clean, organized structure, which makes the code easier to maintain and extend.
Communication: They provide a common vocabulary for developers, improving collaboration and understanding in a team.
Flexibility: Design patterns encourage loose coupling and high cohesion, enabling more adaptable and flexible code.
Best Practices: They embody software engineering best practices, helping avoid common pitfalls like tightly coupled systems and code duplication.
Answer:
Design Patterns are reusable solutions to common software design problems. They are not finished code but templates that help solve recurring design issues in software development.
Example: Instead of writing a new way to create objects every time, you can use the Factory Pattern.
Purpose: To improve code readability, maintainability, and flexibility.
Answer:
Design Patterns are generally classified into three main categories:
Creational Patterns: Deal with object creation.
Examples: Singleton, Factory, Abstract Factory, Builder, Prototype.
Structural Patterns: Deal with object composition and relationships.
Examples: Adapter, Decorator, Facade, Composite, Proxy.
Behavioral Patterns: Deal with object interaction and responsibility.
Examples: Observer, Strategy, Command, Iterator, Mediator.
Answer:
The Singleton Pattern ensures that a class has only one instance and provides a global access point to it.
Use Case: Database connection, Logger class.
Example in Java:
public class Singleton {
private static Singleton instance;
private Singleton() {} // private constructor
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Advantage: Saves memory and ensures only one instance.
Disadvantage: Can cause issues in multithreaded environments if not handled properly.
Answer:
The Factory Pattern provides a method to create objects without specifying the exact class of object that will be created.
Use Case: GUI libraries where you can create different types of buttons.
Example in Java:
interface Shape {
void draw();
}
class Circle implements Shape {
public void draw() { System.out.println("Drawing Circle"); }
}
class ShapeFactory {
public Shape getShape(String shapeType) {
if(shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
}
return null;
}
}
Answer:
The Observer Pattern is a behavioral design pattern where one object (subject) notifies other objects (observers) automatically when its state changes.
Use Case: Event handling systems like a news app sending updates to subscribers.
Example:
interface Observer {
void update(String message);
}
class NewsAgency {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) { observers.add(observer); }
public void notifyObservers(String news) {
for (Observer obs : observers) obs.update(news);
}
}
Answer:
The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable at runtime.
Use Case: Payment methods in e-commerce websites (Credit Card, PayPal, UPI).
Example:
interface PaymentStrategy {
void pay(int amount);
}
class CreditCardPayment implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Paid " + amount + " using Credit Card");
}
}
Answer:
The Adapter Pattern allows incompatible interfaces to work together by acting as a bridge between them.
Use Case: Connecting an old system with a new system.
Example:
interface OldSystem {
void oldMethod();
}
class NewSystem {
public void newMethod() { System.out.println("New System method"); }
}
class Adapter implements OldSystem {
NewSystem newSystem = new NewSystem();
public void oldMethod() { newSystem.newMethod(); }
}
Answer:
The Decorator Pattern allows you to add new functionality to an existing object dynamically without altering its structure.
Use Case: Adding features to a GUI component.
Example: Adding scrollbars to a window dynamically.
Answer:
The Builder Pattern is used to construct complex objects step by step, separating the construction and representation.
Use Case: Building a complex Meal object in a restaurant application.
Example:
class MealBuilder {
private Meal meal = new Meal();
public MealBuilder addBurger() { meal.add("Burger"); return this; }
public MealBuilder addDrink() { meal.add("Coke"); return this; }
public Meal build() { return meal; }
}
Answer:
The Prototype Pattern is used to create a copy of an existing object rather than creating a new one.
Use Case: Cloning objects for performance optimization.
Example:
class Employee implements Cloneable {
String name;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Answer:
The Facade Pattern provides a simplified interface to a complex subsystem.
Use Case: Simplifying interaction with a complex library.
Example: A single HomeTheaterFacade class controlling DVD, Lights, and Sound.
| Feature | Factory Pattern | Builder Pattern |
|---|---|---|
| Purpose | Creates objects without exposing logic | Builds complex objects step by step |
| Complexity | Simple | Complex |
| Object Creation | Single step | Multi-step |
Answer:
Makes code reusable and maintainable.
Provides solutions to common problems.
Helps in understanding OOP principles better.
Increases interview confidence for coding/design questions.
Answer:
The Abstract Factory Pattern provides an interface to create families of related or dependent objects without specifying their concrete classes.
Use Case: GUI toolkit supporting multiple operating systems (Windows, MacOS).
Example:
interface Button { void paint(); }
class WindowsButton implements Button { public void paint(){ System.out.println("Windows Button"); } }
class MacButton implements Button { public void paint(){ System.out.println("Mac Button"); } }
interface GUIFactory { Button createButton(); }
class WindowsFactory implements GUIFactory { public Button createButton() { return new WindowsButton(); } }
class MacFactory implements GUIFactory { public Button createButton() { return new MacButton(); } }
Answer:
The Command Pattern encapsulates a request as an object, allowing parameterization of clients with queues, requests, or operations.
Use Case: Undo/Redo operations in text editors, remote control buttons.
Example: Each button on a remote can be a Command object.
Answer:
The Mediator Pattern reduces direct communication between objects and centralizes interaction through a mediator.
Use Case: Chat applications where a mediator manages communication between users.
Example: ChatRoom class mediates messages between User objects.
Answer:
The Iterator Pattern provides a way to access elements of a collection sequentially without exposing its underlying representation.
Use Case: Traversing a list, set, or map.
Example:
Iterator<String> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
Answer:
The State Pattern allows an object to change its behavior based on its internal state.
Use Case: Order status in e-commerce (Ordered, Shipped, Delivered).
Example: Different State classes implement behavior for each order stage.
Answer:
Allows cloning objects instead of creating new ones.
Reduces the cost of object creation, especially if the object is heavy to initialize.
Example: Cloning a game character with the same attributes.
Answer:
The Flyweight Pattern reduces memory usage by sharing common parts of objects.
Use Case: Text editor storing character formatting; same font objects are shared.
Example: A Character object represents a letter with shared font style.
Answer:
The Proxy Pattern provides a surrogate or placeholder for another object to control access.
Use Case: Lazy loading in Hibernate, protecting sensitive resources.
Example: A ProxyImage loads the actual image only when requested.
| Feature | Singleton | Factory |
|---|---|---|
| Purpose | Only one instance of a class | Creates multiple objects |
| Creation | Controlled, lazy initialization | Flexible object creation |
| Use Case | Database connection, Logger | GUI components, Shapes |
| Feature | Observer | Mediator |
|---|---|---|
| Purpose | Notify dependent objects | Centralized communication |
| Coupling | Loosely coupled | Reduces direct coupling |
| Use Case | Event-driven programming | Chat apps, Air Traffic Control |
Answer:
The Template Method Pattern defines the skeleton of an algorithm in a base class but allows subclasses to override specific steps.
Use Case: Preparing beverages (Coffee, Tea).
Example: Base class Beverage has prepareRecipe(), subclasses implement brew() and addCondiments().
Answer:
The Bridge Pattern decouples an abstraction from its implementation so they can vary independently.
Use Case: Separating a Shape hierarchy from Rendering APIs.
Example: Circle shape uses VectorRenderer or RasterRenderer.
Answer:
It passes a request along a chain of handlers until one of the handlers processes it.
Use Case: Logging systems (INFO, DEBUG, ERROR).
Example: ErrorHandler -> FileLogger -> EmailLogger.
Answer:
The Memento Pattern captures and restores an object's previous state without exposing its internal structure.
Use Case: Undo functionality in text editors.
Example: TextEditor saves snapshots, which can be restored.
Answer:
The Visitor Pattern lets you define a new operation without changing the classes of elements on which it operates.
Use Case: Performing operations on a collection of different objects like employees or shapes.
Example: Employee class can accept a Visitor to calculate salary or display info.
| Feature | Structural | Creational |
|---|---|---|
| Purpose | Composition of classes/objects | Object creation |
| Example | Adapter, Decorator, Proxy | Singleton, Factory, Builder |
| Focus | How classes are connected | How objects are instantiated |
| Feature | Behavioral | Structural |
|---|---|---|
| Purpose | Object interaction and communication | Object composition and relationships |
| Example | Observer, Strategy, Command | Decorator, Adapter, Facade |
| Focus | How objects interact | How objects are composed |
Helps understand object-oriented principles.
Provides ready solutions for common problems.
Improves code readability and maintainability.
Enhances interview confidence.
| Pattern | Real-World Example |
|---|---|
| Singleton | Database connection pool, Logger |
| Factory | GUI button creation (Windows/Mac) |
| Observer | Event listeners in UI (Button click) |
| Builder | Creating a complex meal in a restaurant app |
| Adapter | Connecting old power plug to a new socket |
| Strategy | Payment methods in e-commerce |
| Decorator | Adding scrollbars, borders in GUI |
| Facade | Home theater system control |
| Proxy | Image lazy loading |
Answer:
Design Patterns are proven, reusable solutions to recurring software design problems.
For experienced developers:
They improve code quality, maintainability, and scalability.
Help in architectural decision-making.
Aid in communication, since patterns have common terminology.
Example: Using a Singleton for a centralized logging service avoids creating multiple loggers and ensures consistency.
| Feature | Design Pattern | Framework |
|---|---|---|
| Definition | Reusable solution template | Reusable software platform |
| Scope | Specific problem-solving | Broad application support |
| Implementation | Manually implemented | Provided as a ready-to-use library |
Answer:
Ensures a class has only one instance with global access.
Variations:
Eager Initialization: Object created at class loading time.
Lazy Initialization: Object created when needed.
Thread-Safe Singleton: Uses synchronized or volatile keyword.
Bill Pugh Singleton: Uses inner static helper class (best practice in Java).
Example (Thread-Safe Lazy Initialization in Java):
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;
}
}
Answer:
Factory Method: Creates a single product (e.g., ShapeFactory.createShape("Circle")).
Abstract Factory: Creates a family of related products without specifying concrete classes (e.g., GUIFactory creating Button and TextBox for Windows or Mac).
Use Case: GUI toolkit supporting multiple OS themes.
Answer:
Builder Pattern is used to construct complex objects step by step, separating construction and representation.
Use Case: Constructing immutable objects or complex JSON/XML objects.
Example:
User user = new User.Builder()
.setName("John")
.setEmail("john@example.com")
.setAge(30)
.build();
Advantage: Clean code, immutable objects.
Disadvantage: More classes and code complexity.
| Feature | Builder | Factory |
|---|---|---|
| Purpose | Construct complex objects | Create objects |
| Steps | Multi-step | Single-step |
| Use Case | Building an object with optional parameters | Creating a shape or component |
Answer:
Observer Pattern: One-to-many dependency where observers are notified of changes in subject.
Use Case: Event-driven systems, stock price updates.
Advantage: Loose coupling, dynamic subscription.
Disadvantage: Too many observers can slow performance; can create memory leaks if not deregistered.
Example: Event Listeners in Java Swing.
Answer:
Strategy Pattern: Encapsulates algorithms and makes them interchangeable at runtime.
Use Case: Payment methods in e-commerce (Credit Card, PayPal, UPI).
Example:
interface PaymentStrategy { void pay(int amount); }
class CreditCardPayment implements PaymentStrategy { ... }
class PayPalPayment implements PaymentStrategy { ... }
Advantage: Supports open/closed principle (add new strategy without changing existing code).
| Feature | Strategy | State |
|---|---|---|
| Purpose | Choose algorithm at runtime | Change behavior based on state |
| Context | External | Internal |
| Example | Sorting algorithms | TCP Connection (Listening, Closed, Established) |
Answer:
Allows adding behavior dynamically to an object without modifying its structure.
Use Case: GUI components (scrollbars, borders), logging enhancements.
Example:
Component component = new TextBox();
Component decorated = new ScrollDecorator(new BorderDecorator(component));
Advantage: Open/Closed principle.
Disadvantage: Can lead to complex layers of decorators.
Answer:
Adapter Pattern bridges incompatible interfaces, allowing them to work together.
Use Case: Legacy system integration, database migration.
Example: Power plug adapter (3-pin to 2-pin).
Types:
Object Adapter (uses composition)
Class Adapter (uses inheritance)
Answer:
Provides a simplified interface to a complex subsystem.
Use Case: Home theater control system (DVD, Lights, Sound).
Advantage: Reduces dependency, easier to use.
Disadvantage: Might hide too much functionality.
Answer:
Proxy acts as a surrogate for another object to control access.
Use Case: Lazy loading, security control, remote proxies.
Example: ImageProxy loads image only when requested.
Answer:
Defines skeleton of an algorithm in a base class and lets subclasses override steps.
Use Case: Preparing beverages (Tea, Coffee).
Advantage: Code reuse, consistent algorithm.
Disadvantage: Rigid base class hierarchy.
Answer:
Passes a request along a chain of handlers until one handles it.
Use Case: Logging (INFO, DEBUG, ERROR), support ticket routing.
Advantage: Decouples sender and receiver.
Disadvantage: No guarantee request is handled.
Answer:
Centralizes communication between objects to reduce direct dependencies.
Use Case: Chat application, air traffic control system.
Advantage: Reduces coupling, improves maintainability.
Answer:
Reduces memory consumption by sharing common parts of objects.
Use Case: Text editors (shared character formatting).
Advantage: Efficient memory usage.
Disadvantage: Complexity in separating intrinsic and extrinsic data.
Answer:
Captures and restores an object's internal state without violating encapsulation.
Use Case: Undo/Redo functionality.
Advantage: Maintains encapsulation.
Disadvantage: Can consume memory for many states.
Answer:
Allows adding new operations on objects without modifying their classes.
Use Case: Performing operations on a collection of different objects (employees, shapes).
Advantage: Open/Closed principle.
Disadvantage: Hard to maintain if object structure changes frequently.
| Pattern | Purpose | Use Case |
|---|---|---|
| Builder | Construct complex objects step-by-step | Creating immutable objects, reports |
| Prototype | Clone existing objects | Game characters, templates |
| Factory | Create objects without exposing logic | GUI elements, database connections |
Absolutely! Let’s go deeper into Design Patterns interview questions and answers for experienced developers (4+ years). Here I’ll provide advanced questions, real-world scenarios, and pattern combinations that are commonly asked in interviews at product-based or service-based companies. This will go beyond basic definitions and focus on practical understanding, trade-offs, and implementation considerations.
Answer:
Dependency Injection is a technique where an object receives its dependencies from outside rather than creating them itself.
Pattern Relation: Related to Factory and Strategy patterns.
Use Case: Spring framework in Java.
Example:
class Service {
private Repository repo;
public Service(Repository repo) { this.repo = repo; }
}
Advantage: Promotes loose coupling, easier testing.
| Feature | Proxy | Decorator |
|---|---|---|
| Purpose | Control access to object | Add responsibilities dynamically |
| Example Use Case | Security proxy, lazy loading | Adding scrollbars, borders in GUI |
| Effect on Object | Does not change core behavior | Enhances behavior |
| Feature | Template Method | Strategy |
|---|---|---|
| Definition | Skeleton algorithm defined in base class | Algorithm encapsulated in classes |
| Inheritance vs Composition | Inheritance-based | Composition-based |
| Runtime Flexibility | Low | High |
| Example | Beverage preparation (Tea/Coffee) | Payment methods (Credit/PayPal) |
Answer:
Best practice: Use Bill Pugh Singleton with inner static helper class.
Lazy initialization + thread-safe without synchronization overhead.
public class Singleton {
private Singleton() {}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() { return Holder.INSTANCE; }
}
Answer:
Problem: Observers may be updated concurrently, causing race conditions.
Solution: Use thread-safe collections (e.g., CopyOnWriteArrayList) or synchronized update methods.
Use Case: Real-time stock trading platforms where multiple clients subscribe to price updates.
| Feature | Adapter | Facade |
|---|---|---|
| Purpose | Convert one interface to another | Simplify complex subsystem usage |
| Scope | Single class adaptation | Entire subsystem |
| Use Case | Legacy API integration | Simplified API for complex modules |
Answer:
Yes, patterns are often combined to solve complex problems.
Example:
Scenario: An e-commerce platform
Builder for creating complex Order objects
Strategy for multiple payment options
Observer for sending notifications to customers
Singleton for central logging
| Feature | Flyweight | Prototype |
|---|---|---|
| Purpose | Share objects to save memory | Clone objects to create copies |
| Data | Intrinsic vs Extrinsic data | Full object copy |
| Use Case | Text editor fonts | Cloning game characters |
Answer:
Pattern Used: Command + Memento
Command: Encapsulates action (do/undo).
Memento: Stores state before action.
Use Case: Text editor, Photoshop.
Answer:
Purpose: Decouple abstraction from implementation.
Scenario: Shape rendering
Abstraction: Shape class
Implementor: VectorRenderer or RasterRenderer
Benefit: Add new shapes or renderers independently.
| Feature | Composite | Decorator |
|---|---|---|
| Purpose | Represents tree structure | Adds functionality dynamically |
| Relationship | Part-Whole hierarchy | Wraps individual object |
| Use Case | File system directories | GUI components enhancements |
Answer:
Purpose: Pass request along a chain until handled.
Scenario: Logging system: INFO -> DEBUG -> ERROR
Implementation: Each logger checks level, passes to next if not handled.
Answer:
Purpose: Perform operations on a collection of objects without changing their classes.
Use Case:
Tax calculation on different employee types
Export different file formats (CSV, XML, JSON)
Benefit: Open/Closed principle; new operations can be added without modifying objects.
Use Prototype when creating a new object is expensive (e.g., loading data from DB) and you can clone an existing object.
Use Factory when object creation is simple and configurable.
Advantages: Undo functionality without exposing internal state.
Disadvantages: Memory usage increases with frequent snapshots.
Optimization: Use incremental mementos instead of full object state.
Deregister observers when no longer needed
Use weak references in languages like Java to avoid strong reference retention
Example: WeakReference<Observer> in observer list
How would you design a notification system for multiple channels (SMS, Email, Push)?
Observer + Strategy + Singleton
How would you design a report generation system with multiple formats?
Builder + Strategy + Template Method
How would you design a caching system?
Proxy + Singleton + Flyweight