Design Pattern Interview Preparation
A. Design Pattern Fundamentals A Design Pattern is a proven, reusable solution to a commonly occurring software design problem. It is not a ready-made code or framework, butβ¦
A. Design Pattern Fundamentals
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
A Design Pattern is a proven, reusable solution to a commonly occurring software design problem.
It is not a ready-made code or framework, but a template or blueprint that shows how to solve a particular design problem in an efficient and maintainable way.
Design patterns were popularized by the Gang of Four (GoF) in their book *Design Patterns: Elements of Reusable Object-Oriented Software*.
Simply put,
“Design patterns are best practices collected from experienced software developers.”
Real-Life Example
Imagine building a house.
If every architect designs stairs differently, construction becomes difficult.
Instead, architects use standard blueprints that are already tested.
Similarly,
Design Patterns provide standard solutions that developers reuse.
Java Example
Instead of creating database connections repeatedly,
we use the Singleton Pattern so only one connection manager exists.
ConnectionManager manager = ConnectionManager.getInstance;
Advantages
- Reusable solutions
- Reduces development time
- Easier maintenance
- Better readability
- Improves scalability
- Encourages loose coupling
- Makes code easier to test
Interview Tip: Many interviewers ask:
Is Design Pattern a library?
Answer:
No.
It is a design solution or blueprint.
Developers implement it using programming languages.
One-Line Answer
A Design Pattern is a reusable and proven solution to a recurring software design problem that improves code quality, maintainability, and flexibility.
As applications grow larger, problems like:
- Tight coupling
- Code duplication
- Difficult maintenance
- Poor scalability
- Difficult testing
start appearing.
Design Patterns solve these problems by providing standardized solutions.
They help developers write code that is:
- Reusable
- Flexible
- Extensible
- Maintainable
without reinventing the wheel.
Problems Without Design Patterns
Suppose every service directly creates its dependencies.
class OrderService {
PaymentService payment = new PaymentService;
}
Problems:
- Tight coupling
- Difficult to test
- Difficult to replace implementation
Using Dependency Injection (Strategy + IoC)
class OrderService {
private PaymentService payment;
public OrderService(PaymentService payment){
this.payment = payment;
}
}
Now we can inject:
- Stripe
- PayPal
- Razorpay
without changing OrderService.
Benefits
1. Loose Coupling
Objects depend on abstractions instead of concrete classes.
2. Reusability
Same solution can be reused.
3. Easier Testing
Mock implementations can be injected.
4. Better Scalability
Adding new features requires minimal changes.
5. Standardization
Developers across teams understand the same patterns.
Real Project Example
Payment System
Without Pattern
if(payment.equals("PAYPAL")){
}
else if(payment.equals("STRIPE")){
}
else if(payment.equals("UPI")){
}
Using Strategy Pattern
PaymentStrategy strategy;
strategy.pay;
Adding Google Pay only requires a new strategy implementation.
No existing code changes.
One-Line Answer
Design Patterns help solve recurring software design problems by making applications loosely coupled, reusable, scalable, maintainable, and easier to test.
This is a very common interview question.
| Feature | Software Architecture | Design Pattern |
|---|---|---|
| Scope | Entire application | Specific problem |
| Level | High-Level | Low-Level |
| Focus | Overall system structure | Object/Class interaction |
| Purpose | Organize complete application | Solve recurring design problem |
| Examples | Microservices, Monolith, Event-Driven, Layered | Singleton, Factory, Observer, Strategy |
| Size | Large | Small |
| Decision Time | Beginning of project | During implementation |
Example
Suppose we build Amazon.
Architecture decides
- Microservices
- Kafka
- API Gateway
- Database per service
Inside Order Service
we use
- Factory Pattern
- Singleton
- Strategy
- Observer
Architecture is the city plan.
Design Pattern is how each building is constructed.
Interview One-Liner: Architecture defines the overall structure of the system, whereas Design Patterns solve specific design problems inside that architecture.
According to GoF, Design Patterns are divided into three categories.
| Creational | Structural | Behavioral |
|---|---|---|
| Creates objects | Organizes objects | Manages communication |
| Focus on instantiation | Focus on composition | Focus on interaction |
| Reduces object creation complexity | Simplifies object relationships | Improves object collaboration |
| Examples: Singleton, Factory | Adapter, Proxy, Decorator | Strategy, Observer, Command |
Example
Food Delivery App
Creational
RestaurantFactory.createRestaurant
Structural
PaymentAdapter
Behavioral
NotificationObserver
Interview One-Liner: Creational patterns deal with object creation, Structural patterns organize classes and objects, while Behavioral patterns define how objects communicate.
SOLID principles are object-oriented design principles, while Design Patterns are reusable solutions that often implement those principles.
In simple words,
SOLID tells us what good design looks like, while Design Patterns show how to achieve it.
Many design patterns are built around SOLID principles.
Relationship
| SOLID Principle | Supported Design Patterns |
|---|---|
| Single Responsibility (SRP) | Factory, Builder |
| Open/Closed (OCP) | Strategy, Decorator |
| Liskov Substitution (LSP) | Strategy, Template Method |
| Interface Segregation (ISP) | Adapter, Bridge |
| Dependency Inversion (DIP) | Factory, Strategy, Dependency Injection |
Example
Without Strategy
if(payment.equals("UPI")){
}
else{
}
Violates Open/Closed Principle.
Using Strategy
PaymentStrategy
Add new payment methods without modifying existing code.
Interview One-Liner: SOLID principles guide good object-oriented design, while Design Patterns provide practical implementations of those principles to create flexible and maintainable software.
This is one of the most frequently asked design questions.
Composition means building classes by combining objects instead of inheriting behavior.
Instead of saying
“is-a”
Composition says
“has-a”
It provides greater flexibility because behavior can be changed at runtime by replacing composed objects.
Example
Inheritance
class Bird {
void fly {}
}
class Penguin extends Bird {
}
Problem:
Penguins cannot fly.
Inheritance forces unwanted behavior.
Composition
interface FlyBehavior {
void fly;
}
class CanFly implements FlyBehavior {
public void fly {
System.out.println("Flying");
}
}
class CannotFly implements FlyBehavior {
public void fly {
System.out.println("Cannot fly");
}
}
class Bird {
private FlyBehavior flyBehavior;
Bird(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
void performFly {
flyBehavior.fly;
}
}
Now:
Bird eagle = new Bird(new CanFly);
Bird penguin = new Bird(new CannotFly);
Advantages
- Loose coupling
- Runtime flexibility
- Better testing
- Reusable behavior
- Avoids inheritance hierarchy explosion
Real Project Example
Spring Boot uses composition heavily.
A service contains:
- Repository
- Validator
- KafkaProducer
- CacheService
instead of inheriting from them.
class OrderService {
private OrderRepository repository;
private NotificationService notification;
}
One-Line Answer
Composition is preferred over inheritance because it provides greater flexibility, promotes loose coupling, and allows behavior to be changed at runtime.
One of the most important object-oriented design principles and widely used in Spring Framework.
Instead of depending on a concrete class, classes should depend on an interface (abstraction).
This allows implementations to be replaced without changing the client code.
This principle is the foundation of:
- Spring Dependency Injection
- Strategy Pattern
- Factory Pattern
- Proxy Pattern
- Dependency Inversion Principle (DIP)
Bad Example
class OrderService {
MySQLRepository repository = new MySQLRepository;
}
Problems:
- Tight coupling
- Difficult testing
- Cannot replace implementation easily
Good Example
interface Repository {
void save;
}
class MySQLRepository implements Repository {
public void save {}
}
class MongoRepository implements Repository {
public void save {}
}
class OrderService {
private Repository repository;
OrderService(Repository repository) {
this.repository = repository;
}
}
Now we can switch implementations without modifying OrderService.
Spring Boot Example
@Autowired
private UserRepository repository;
UserRepository is an interface, and Spring injects the implementation automatically.
Advantages
- Loose coupling
- Easy unit testing with mocks
- Easier implementation replacement
- Supports polymorphism
- Works seamlessly with Dependency Injection
Interview One-Liner: Favor interfaces over implementations means depending on abstractions rather than concrete classes, resulting in loosely coupled, flexible, and easily testable applications.
B. Singleton Pattern
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Singleton is a Creational Design Pattern that ensures only one instance of a class exists throughout the application and provides a global access point to it.
Use Cases
- Configuration Manager
- Logger
- Cache Manager
- Database Connection Pool
- Spring Beans (by default)
Basic Implementation
public class Singleton {
private static final Singleton INSTANCE = new Singleton;
private Singleton {}
public static Singleton getInstance {
return INSTANCE;
}
}
Advantages
- Saves memory
- Centralized access
- Controlled object creation
Interview One-Liner: Singleton ensures only one object of a class exists and provides a global access point to it.
| Type | Thread Safe | Lazy Loading | Performance |
|---|---|---|---|
| Eager Initialization | β | β | Fast |
| Lazy Initialization | β | β | Fast |
| Synchronized Method | β | β | Slow |
| Double Checked Locking | β | β | Fast |
| Bill Pugh Singleton | β | β | Best |
| Enum Singleton | β | β | Safest |
| Eager | Lazy |
|---|---|
| Object created at startup | Created when first needed |
| Faster access | Saves memory |
| May waste memory | Better for expensive objects |
| Thread-safe | Not thread-safe by default |
Eager
private static final Singleton INSTANCE = new Singleton;
Lazy
private static Singleton instance;
public static Singleton getInstance {
if (instance == null) {
instance = new Singleton;
}
return instance;
}
Interview One-Liner: Eager creates the instance during class loading, while Lazy creates it only on the first request.
Problem
Two threads may create two different objects simultaneously.
Solution
Synchronize the method.
public static synchronized Singleton getInstance {
if (instance == null)
instance = new Singleton;
return instance;
}
Drawback
- Slow due to synchronization on every call.
Avoids synchronization after the instance is created.
private static volatile Singleton instance;
public static Singleton getInstance {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton;
}
}
return instance;
}
Why volatile?
Prevents instruction reordering and ensures visibility across threads.
Interview One-Liner: Double Checked Locking improves performance by synchronizing only during the first object creation.
Uses a static inner class.
public class Singleton {
private Singleton{}
private static class Holder {
private static final Singleton INSTANCE = new Singleton;
}
public static Singleton getInstance {
return Holder.INSTANCE;
}
}
Advantages
- Lazy loading
- Thread-safe
- No synchronization overhead
Interview Tip: Preferred implementation in Java.
public enum Singleton {
INSTANCE;
}
Advantages
- Thread-safe
- Prevents Reflection
- Prevents Serialization issues
- Prevents Cloning
Interview Tip: Joshua Bloch recommends Enum Singleton.
Reflection
Reflection can invoke the private constructor and create another object.
Constructor<Singleton> c = Singleton.class.getDeclaredConstructor;
c.setAccessible(true);
Singleton obj = c.newInstance;
Serialization
Deserialization creates a new object.
ObjectInputStream.readObject;
Cloning
Calling clone creates another object.
singleton.clone;
Reflection
Throw an exception if an instance already exists or use Enum Singleton.
Serialization
Implement readResolve.
protected Object readResolve {
return getInstance;
}
Cloning
Override clone.
@Override
protected Object clone throws CloneNotSupportedException {
throw new CloneNotSupportedException;
}
By default, every Spring Bean is Singleton.
@Service
public class OrderService {
}
- One object per Spring IoC Container.
- Not the same as the classic GoF Singleton (Spring manages lifecycle).
Interview One-Liner: Spring beans are singleton by default, but the scope is per IoC container, not JVM-wide.
| Question | Answer |
|---|---|
| What is Singleton? | Only one instance with global access. |
| Best implementation? | Bill Pugh or Enum Singleton. |
| Thread-safe? | Synchronized, DCL, Bill Pugh, Enum. |
| Why volatile? | Prevents instruction reordering. |
| Can Reflection break Singleton? | Yes. |
| Can Serialization break Singleton? | Yes. |
| Can Cloning break Singleton? | Yes. |
| Spring Singleton? | One bean instance per IoC container. |
C. Factory Pattern
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Factory Pattern is a Creational Design Pattern that creates objects without exposing the object creation logic to the client. The client requests an object from a factory instead of using new.
Example
Shape shape = ShapeFactory.getShape("CIRCLE");
shape.draw;
Advantages
- Loose coupling
- Encapsulates object creation
- Easy to extend
- Supports Open/Closed Principle
Interview One-Liner: Factory Pattern delegates object creation to a factory, reducing coupling between the client and concrete classes.
| Simple Factory | Factory Method |
|---|---|
| One factory class | Factory method defined in parent, implemented by subclasses |
| Uses if/else or switch | Uses inheritance and polymorphism |
| Not a GoF pattern | GoF Design Pattern |
| Less flexible | More extensible |
Interview Tip: Simple Factory is a coding style, whereas Factory Method is an official GoF Design Pattern.
| Factory Method | Abstract Factory |
|---|---|
| Creates one product | Creates a family of related products |
| Uses one factory method | Uses multiple factory methods |
| Simpler | More complex |
| Example: Create Car | Example: Create Car + Engine + Tyres |
Example
Factory Method
Car car = factory.createCar;
Abstract Factory
VehicleFactory factory = new BMWFactory;
factory.createCar;
factory.createEngine;
Interview One-Liner: Factory Method creates one object, while Abstract Factory creates a group of related objects.
- Loose coupling
- Hides object creation logic
- Easy to add new implementations
- Promotes Open/Closed Principle
- Improves maintainability
- Simplifies testing with interfaces
- Calendar.getInstance
- NumberFormat.getInstance
- ResourceBundle.getBundle
- DocumentBuilderFactory.newInstance
- DriverManager.getConnection
Spring uses the Factory Pattern extensively.
Examples:
- BeanFactory
- ApplicationContext
- FactoryBean
- Bean creation by the IoC container
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
OrderService service = context.getBean(OrderService.class);
Interview Tip: You never create Spring beans using new; Spring acts as the factory and creates/manages them.
| Question | Answer |
|---|---|
| What is Factory Pattern? | Delegates object creation to a factory. |
| Simple Factory vs Factory Method | Simple Factory uses if/else; Factory Method uses inheritance. |
| Factory Method vs Abstract Factory | One product vs family of related products. |
| Benefits | Loose coupling, extensibility, maintainability. |
| Java Examples | Calendar.getInstance, NumberFormat.getInstance, DocumentBuilderFactory.newInstance. |
| Spring Example | BeanFactory, ApplicationContext, FactoryBean. |
D. Abstract Factory Pattern
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Abstract Factory is a Creational Design Pattern that provides an interface to create a family of related or dependent objects without specifying their concrete classes.
Example
A GUIFactory can create:
- Button
- Checkbox
- TextBox
for different operating systems (Windows, Mac).
Interview One-Liner: Abstract Factory creates a family of related objects without exposing their concrete implementations.
Use Abstract Factory when:
- Multiple related objects need to be created together.
- The system should support multiple product families.
- You want to switch entire product families without changing client code.
Example
A Car Factory creates:
- Car
- Engine
- Tyres
BMW Factory β BMW Car + BMW Engine + BMW Tyres
Audi Factory β Audi Car + Audi Engine + Audi Tyres
| Factory Method | Abstract Factory |
|---|---|
| Creates one product | Creates a family of related products |
| Simpler | More complex |
| One factory method | Multiple factory methods |
| Example: Car | Example: Car + Engine + Tyres |
Interview One-Liner: Factory Method creates a single object, whereas Abstract Factory creates a group of related objects.
Java
- DocumentBuilderFactory
- TransformerFactory
- XPathFactory
Spring
- BeanFactory
- ApplicationContext
Real-life Example
Furniture Factory:
- Modern Chair
- Modern Sofa
- Modern Table
Victorian Factory:
- Victorian Chair
- Victorian Sofa
- Victorian Table
| Question | Answer |
|---|---|
| What is Abstract Factory? | Creates a family of related objects. |
| When to use? | When multiple related objects must be created together. |
| Factory vs Abstract Factory | One product vs family of products. |
| Java Examples | DocumentBuilderFactory, TransformerFactory. |
E. Builder Pattern
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Builder is a Creational Design Pattern used to create complex objects step by step, especially when an object has many optional parameters.
Example
User user = User.builder
.name("John")
.email("john@test.com")
.age(30)
.build;
Interview One-Liner: Builder Pattern constructs complex objects step by step and improves code readability.
Constructors become difficult to manage when a class has many optional parameters.
Without Builder
User user = new User("John", "john@test.com", 30, "Delhi", "9999999999");
It’s hard to remember the parameter order.
With Builder
User user = User.builder
.name("John")
.age(30)
.build;
Much more readable and flexible.
When multiple constructors are created to support different parameter combinations, it leads to constructor overload explosion.
User
User(String name)
User(String name, int age)
User(String name, int age, String city)
User(String name, int age, String city, String email)
Solution
Use the Builder Pattern instead of creating numerous overloaded constructors.
Interview One-Liner: Builder solves the Telescoping Constructor Problem by replacing multiple overloaded constructors with a fluent API.
Builder is commonly used to create immutable objects.
- Fields are final
- No setters
- Values are assigned only once during object creation
Benefits
- Thread-safe
- Easy to maintain
- Prevents accidental modification
Lombok generates the Builder code automatically.
@Builder
public class User {
private String name;
private String email;
}
Usage:
User user = User.builder
.name("John")
.email("john@test.com")
.build;
Interview Tip: @Builder reduces boilerplate code while implementing the Builder Pattern.
Spring internally uses the Builder Pattern in several APIs.
Examples:
- ResponseEntity.ok.body(data)
- UriComponentsBuilder
- WebClient.builder
- RestTemplateBuilder
- MockMvcRequestBuilders
Example:
WebClient client = WebClient.builder
.baseUrl("http://localhost:8080")
.build;
| Question | Answer |
|---|---|
| What is Builder Pattern? | Creates complex objects step by step. |
| Why Builder? | Improves readability and handles optional parameters. |
| Telescoping Constructor Problem | Too many overloaded constructors. |
| Immutable Objects | Builder creates immutable objects without setters. |
| Lombok | @Builder generates Builder code automatically. |
| Spring Examples | WebClient.builder, ResponseEntity, RestTemplateBuilder, UriComponentsBuilder. |
F. Prototype Pattern
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Prototype is a Creational Design Pattern that creates new objects by cloning an existing object instead of creating them from scratch.
Useful when object creation is expensive.
Interview One-Liner: Prototype creates new objects by copying an existing object.
| Shallow Copy | Deep Copy |
|---|---|
| Copies object references | Copies complete object graph |
| Nested objects are shared | Nested objects are cloned |
| Faster | More memory and time |
| Changes affect original | Completely independent |
Interview Tip: Shallow copy shares references, while deep copy creates independent copies.
Java provides the clone method through the Cloneable interface.
Employee emp2 = emp1.clone;
Drawbacks
- Complex for deep copying
- Cloneable has design issues
- Copy constructors or Builder are often preferred
Use Prototype when:
- Object creation is expensive.
- Creating similar objects repeatedly.
- Copying an existing configuration is easier than rebuilding.
Examples
- Game objects
- Document templates
- Employee templates
| Question | Answer |
|---|---|
| What is Prototype? | Creates objects by cloning existing ones. |
| Shallow vs Deep Copy | Shared references vs independent copies. |
| clone | Used to clone objects; not always recommended. |
| When to use? | Expensive object creation or similar object copies. |
G. Structural Design Patterns
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Adapter is a Structural Design Pattern that allows incompatible interfaces to work together by acting as a bridge.
Real-life Example
Power plug adapter.
Java Example
Arrays.asList adapts an array into a List.
Interview One-Liner: Adapter converts one interface into another so incompatible classes can work together.
- Power Adapter
- Arrays.asList
- InputStreamReader
- Payment Gateway Adapter
| Adapter | Facade |
|---|---|
| Makes incompatible interfaces compatible | Simplifies a complex subsystem |
| Existing interface cannot change | Provides a simplified interface |
| Focuses on compatibility | Focuses on simplicity |
Interview Tip: Adapter = Compatibility, Facade = Simplicity.
Decorator dynamically adds new behavior to an object without modifying its class.
Example
Coffee β Add Milk β Add Sugar β Add Cream
Interview One-Liner: Decorator adds responsibilities to an object dynamically.
| Decorator | Inheritance |
|---|---|
| Runtime behavior change | Compile-time behavior |
| Flexible | Less flexible |
| Uses composition | Uses inheritance |
Interview Tip: Decorator follows Composition over Inheritance.
Java I/O heavily uses the Decorator Pattern.
BufferedInputStream
BufferedReader
DataInputStream
PrintWriter
Facade provides a single simplified interface to a complex subsystem.
Example
Home Theater Remote controls multiple devices through one interface.
Interview One-Liner: Facade hides complexity by providing a simple unified interface.
- Hides complexity
- Reduces coupling
- Improves readability
- Simplifies client code
- JdbcTemplate
- RestTemplate
- KafkaTemplate
- JmsTemplate
These simplify complex APIs behind a single interface.
Proxy provides a placeholder or surrogate for another object to control access to it.
Use Cases
- Security
- Logging
- Lazy Loading
- Caching
- Transactions
Interview One-Liner: Proxy controls access to another object without changing its code.
| Static Proxy | Dynamic Proxy |
|---|---|
| Written manually | Generated at runtime |
| More boilerplate | Less code |
| Less flexible | Highly flexible |
| JDK Proxy | CGLIB |
|---|---|
| Works with interfaces | Works with classes |
| Uses java.lang.reflect.Proxy | Creates subclasses using bytecode |
| Faster creation | Slightly faster method calls |
Interview Tip: – JDK Proxy β Interface-based
- CGLIB β Class-based
Spring AOP uses proxies to implement:
- @Transactional
- @Cacheable
- @Async
- @Secured
If a bean implements an interface β JDK Proxy
Otherwise β CGLIB Proxy
Composite treats individual objects and groups of objects uniformly by organizing them into a tree structure.
Real-life Example
Folder β Subfolder β Files
Interview One-Liner: Composite allows clients to treat single objects and collections of objects the same way.
Company
β
βββ HR Department
βββ IT Department
β βββ Developer
β βββ Tester
βββ Finance Department
Other examples:
- File System
- Organization Hierarchy
- Menu β Submenu β Menu Item
| Pattern | Purpose | Java/Spring Example |
|---|---|---|
| Adapter | Makes incompatible interfaces compatible | Arrays.asList, InputStreamReader |
| Decorator | Adds behavior dynamically | BufferedInputStream, BufferedReader |
| Facade | Simplifies complex APIs | JdbcTemplate, RestTemplate, KafkaTemplate |
| Proxy | Controls access to an object | Spring AOP, @Transactional, @Cacheable |
| Composite | Represents part-whole tree structures | File System, Organization Hierarchy |
H. Behavioral Design Patterns
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Strategy is a Behavioral Design Pattern that defines a family of algorithms, encapsulates each one, and allows them to be selected at runtime.
Instead of using multiple if-else or switch statements, each algorithm is implemented as a separate strategy.
Example
Payment Methods:
- Credit Card
- UPI
- PayPal
Advantages
- Eliminates if-else
- Follows Open/Closed Principle
- Easy to add new algorithms
- Promotes Composition over Inheritance
Spring Example
Different PaymentService implementations injected using interfaces.
Interview One-Liner: Strategy encapsulates interchangeable algorithms and allows selecting one at runtime.
Observer is a Behavioral Design Pattern where one object (Subject) notifies multiple dependent objects (Observers) whenever its state changes.
Example
Order Placed β Notify:
- Email Service
- SMS Service
- Inventory Service
Java Example
java.util.Observer *(legacy)*, Event Listeners.
Spring Example
- ApplicationEventPublisher
- @EventListener
Advantages
- Loose coupling
- One-to-many communication
- Easy to add new observers
Interview One-Liner: Observer allows multiple objects to automatically receive updates when another object’s state changes.
Template Method defines the overall algorithm in a base class while allowing subclasses to customize specific steps.
Example
Making Tea and Coffee:
- Boil Water β
- Brew β (changes)
- Pour into Cup β
- Add Ingredients β (changes)
Advantages
- Code reuse
- Consistent algorithm flow
- Easy customization
Java Example
- AbstractList
- HttpServlet
Interview One-Liner: Template Method defines an algorithm skeleton while allowing subclasses to customize specific steps.
Command encapsulates a request as an object, allowing requests to be parameterized, queued, logged, or undone.
Example
Remote Control:
- Turn ON
- Turn OFF
- Volume Up
Each action is a command object.
Advantages
- Loose coupling
- Supports Undo/Redo
- Easy to queue or log requests
Java Example
- Runnable
- Callable
- ActionListener
Interview One-Liner: Command converts a request into an object, enabling flexible execution and undo functionality.
Chain of Responsibility passes a request through a chain of handlers until one of them processes it.
Example
Authentication Request:
- JWT Filter
- Authentication Filter
- Authorization Filter
Advantages
- Loose coupling
- Flexible request processing
- Easy to add/remove handlers
Spring Example
- Spring Security Filter Chain
- Servlet Filters
Interview One-Liner: Chain of Responsibility passes a request through multiple handlers until it is handled.
State Pattern allows an object to change its behavior when its internal state changes, without using complex if-else statements.
Example
Order States:
- New
- Paid
- Shipped
- Delivered
- Cancelled
Each state defines different behavior.
Advantages
- Removes complex conditional logic
- Easy to add new states
- Better maintainability
Interview One-Liner: State Pattern changes an object’s behavior based on its current state.
Iterator provides a standard way to traverse a collection without exposing its internal implementation.
Java Example
Iterator<String> iterator = list.iterator;
while (iterator.hasNext) {
System.out.println(iterator.next);
}
Advantages
- Sequential access
- Hides collection implementation
- Supports different collection types uniformly
Java Examples
- Iterator
- ListIterator
- Enhanced for loop
Interview One-Liner: Iterator provides a uniform way to traverse elements of a collection without exposing its internal structure.
| Pattern | Purpose | Java/Spring Example |
|---|---|---|
| Strategy | Select algorithm at runtime | Payment Strategy, Comparator |
| Observer | Notify multiple objects on state change | @EventListener, ApplicationEventPublisher |
| Template Method | Define algorithm skeleton | AbstractList, HttpServlet |
| Command | Encapsulate requests as objects | Runnable, Callable |
| Chain of Responsibility | Pass request through handlers | Spring Security Filter Chain, Servlet Filters |
| State | Change behavior based on state | Order Status, Workflow Engine |
| Iterator | Traverse collections uniformly | Iterator, ListIterator |
J. Production Scenario Questions
Expand a question to read the answer. Tick when youβre prepared (progress saved on this device).
Use the Strategy Pattern.
Each payment method implements the same interface, and the appropriate strategy is selected at runtime.
Example
- Credit Card
- UPI
- PayPal
- Razorpay
- Stripe
Why Strategy?
- Easily add new payment gateways
- No if-else
- Follows Open/Closed Principle
Interview One-Liner: Strategy Pattern is best because payment methods are interchangeable algorithms selected at runtime.
Use the Observer Pattern.
When an event occurs (e.g., Order Placed), all notification channels are notified independently.
Example
Order Placed
β
βββ Email
βββ SMS
βββ Push Notification
Why Observer?
- Loose coupling
- Easy to add new notification channels
- One event triggers multiple actions
Interview One-Liner: Observer Pattern is ideal for event-driven notifications where multiple services react to the same event.
Use the Strategy Pattern.
Instead of:
if(payment.equals("UPI")) { ... }
else if(payment.equals("CARD")) { ... }
Create separate strategy classes implementing a common interface.
Benefits
- Cleaner code
- Easy to extend
- Better maintainability
Interview One-Liner: Replace long if-else chains with the Strategy Pattern.
Use the Template Method Pattern.
Common steps:
- Fetch Data
- Process Data
- Generate Report
Different formats:
- Excel
- CSV
Only the report generation step changes.
Interview One-Liner: Template Method is suitable because the overall workflow remains the same while specific steps vary.
Use the Strategy Pattern.
Each parser implements the same interface.
Example
- CSVParser
- JSONParser
- XMLParser
Parser is selected based on file type.
Interview One-Liner: Strategy Pattern allows different parsing algorithms to be selected dynamically.
Use the Strategy Pattern.
Example
- Festival Discount
- Coupon Discount
- Membership Discount
- Cashback Discount
Each discount rule is implemented as a separate strategy.
Interview One-Liner: Strategy Pattern allows different discount algorithms to be applied without modifying existing code.
Use a combination of:
- Singleton β One Logger instance
- Factory β Create different logger implementations
- Decorator *(optional)* β Add formatting, timestamps, or encryption
Example
- Console Logger
- File Logger
- Database Logger
Interview One-Liner: Singleton manages the logger instance, while Factory creates different logger implementations.
Use the Strategy Pattern.
Example
- JWT Authentication
- OAuth2
- LDAP
- SAML
Each authentication provider implements the same interface.
Interview One-Liner: Strategy Pattern allows switching authentication mechanisms without changing business logic.
Use:
- Proxy Pattern β Check cache before calling the actual service/database.
- Singleton β Shared cache manager instance.
Flow
Client
β
Cache Proxy
β
Cache Hit β Return Data
β
Cache Miss
β
Database
Interview One-Liner: Proxy Pattern adds transparent caching, while Singleton manages the shared cache instance.
Use a combination of:
- Strategy β Different payment gateways
- Factory β Create the required payment strategy
- Dependency Injection (Spring) β Inject implementations
Flow
Payment Request
β
Payment Factory
β
Payment Strategy
β
Stripe / Razorpay / PayPal / UPI
Why?
- Add new gateways without modifying existing code.
- Follows Open/Closed Principle.
- Easy to test and maintain.
Interview One-Liner: Combine Factory and Strategy patterns to build a flexible, pluggable payment system.
| Scenario | Best Pattern |
|---|---|
| Payment Gateway | Strategy |
| Notification Service | Observer |
| Replace long if-else | Strategy |
| Report Generation | Template Method |
| File Parsing (CSV/JSON/XML) | Strategy |
| Multiple Discounts | Strategy |
| Logging Framework | Singleton + Factory (+ Decorator) |
| Authentication Providers | Strategy |
| Cache Layer | Proxy + Singleton |
| Pluggable Payment System | Factory + Strategy + Dependency Injection |