gyanguide interview materials
Design Patterns

Frequently asked design patterns for software developers

Frequently asked patterns for developers:

  • MVC
  • Singleton
  • Factory
  • Observer
  • Strategy
  • Repository
  • Middleware / Chain of Responsibility
  • Decorator
  • Microservices
  • Pub/Sub
  • CQRS
  • Dependency Injection
  • Service Layer

1. MVC (Model View Controller)

MVC stands for Model, View, and Controller. It is one of the most commonly used architectural patterns in web development. The Model handles database operations and business data, the View handles the UI or response layer, and the Controller acts as the middle layer between the Model and View. In MERN or Node.js applications, controllers receive requests, process logic, communicate with models, and send responses back to users.

This pattern helps developers separate concerns properly. Instead of writing all logic in one file, MVC keeps code organized and scalable. For example, in an Express.js application, the route receives a request, the controller processes it, the model communicates with MongoDB, and the response is returned to the frontend. MVC improves maintainability, debugging, testing, and teamwork because frontend, backend, and database logic remain independent.


2. Singleton Pattern

Singleton Pattern ensures that only one instance of a class or object is created during the application lifecycle. This is useful when multiple instances can create problems such as unnecessary memory usage or duplicate database connections. In Node.js applications, Singleton is commonly used for MongoDB database connections, logging systems, cache managers, and configuration objects.

For example, when a Node.js server starts, it creates one MongoDB connection object and reuses it across the application instead of creating a new connection for every request. This improves performance and reduces resource consumption. Singleton also provides a centralized access point, making the system easier to manage and maintain.


3. Factory Pattern

Factory Pattern is used to create objects dynamically without exposing the exact creation logic to the client. Instead of directly creating objects using the new keyword everywhere, a factory method decides which object should be created based on conditions or input parameters.

For example, in a payment system, a factory can create different payment processors like CreditCardPayment, UPI, or PayPal depending on user selection. This pattern improves flexibility and scalability because new object types can be added without changing existing code significantly. It also reduces code duplication and keeps object creation centralized.


4. Observer Pattern

Observer Pattern allows one object to notify multiple dependent objects automatically whenever its state changes. It follows a one-to-many relationship where observers subscribe to a subject and receive updates whenever an event occurs.

This pattern is heavily used in real-time systems such as chat applications, notification systems, stock market trackers, and event-driven architectures. In JavaScript, event listeners are a practical example of the Observer Pattern. For example, when a new message arrives in a chat application, all connected clients automatically receive updates without continuously checking the server manually.


5. Strategy Pattern

Strategy Pattern allows multiple algorithms or behaviors to be selected dynamically at runtime. Instead of writing large conditional statements like if-else or switch, separate strategies are created for each behavior and selected when needed.

For example, an e-commerce website may support multiple payment methods such as UPI, Credit Card, and Wallets. Each payment type can have its own strategy implementation. This makes the code cleaner, easier to maintain, and open for future extensions. Developers can add new strategies without modifying existing business logic, following the Open/Closed Principle.


6. Repository Pattern

Repository Pattern acts as a middle layer between business logic and the database. Instead of directly writing database queries inside controllers or services, all database operations are placed inside repository classes or files.

This pattern improves code organization and separation of concerns. For example, a UserRepository may contain methods like findUser(), createUser(), and updateUser(). If the database changes from MongoDB to PostgreSQL in the future, repository logic can be modified without affecting controllers or services. Repository Pattern also improves testing because database operations can be mocked easily.


7. Middleware / Chain of Responsibility Pattern

Middleware Pattern is widely used in Express.js and works similarly to the Chain of Responsibility Pattern. In this pattern, a request passes through multiple handlers or middleware functions before reaching the final controller.

Each middleware performs a specific task such as authentication, logging, validation, rate limiting, or error handling. For example, an API request may first pass through JWT authentication middleware, then request validation middleware, and finally reach the business logic controller. This pattern keeps code modular and reusable because each middleware has a single responsibility.


8. Decorator Pattern

Decorator Pattern allows additional functionality to be added dynamically to an object without modifying the original object structure. Instead of changing existing code directly, new features are wrapped around the original object.

This pattern is useful for logging, caching, authorization, compression, or analytics features. In React, Higher Order Components (HOC) behave similarly to decorators because they enhance existing components with additional functionality. Decorator Pattern helps maintain clean and extendable code without breaking existing functionality.


9. Microservices Pattern

Microservices Architecture divides a large application into smaller independent services. Each service handles a specific business functionality and communicates with other services through APIs or messaging systems.

For example, an e-commerce platform may have separate services for authentication, payments, orders, inventory, and notifications. Each service can be developed, deployed, and scaled independently. This architecture improves scalability, fault isolation, and deployment flexibility. However, it also introduces challenges like distributed system management, service communication, monitoring, and data consistency.


10. Pub/Sub (Publish Subscribe) Pattern

Pub/Sub Pattern is an event-driven communication model where publishers send messages without knowing who the subscribers are. Subscribers listen for specific events and react when those events occur.

This pattern is commonly used with Kafka, RabbitMQ, Redis Pub/Sub, and Socket.io systems. For example, when an order is placed, the order service publishes an event. Inventory, billing, and notification services subscribe to that event and process their own tasks independently. Pub/Sub improves scalability and reduces tight coupling between services.


11. CQRS (Command Query Responsibility Segregation)

CQRS separates read operations and write operations into different models or services. Commands are responsible for modifying data, while queries are responsible for reading data.

This pattern improves scalability and performance in systems with heavy traffic. For example, in banking applications, write operations like money transfer are separated from read operations like balance checking. CQRS allows separate optimization strategies for reading and writing, making large-scale applications more efficient and maintainable.


12. Dependency Injection (DI)

Dependency Injection is a design pattern where dependencies are provided externally instead of being created inside a class or function. This reduces tight coupling between components.

For example, instead of a service directly creating a database object internally, the database connection is injected into the service. This improves testing, flexibility, and maintainability. DI is heavily used in frameworks like Angular, Spring Boot, and NestJS. It also supports mock testing because dependencies can easily be replaced during testing.


13. Service Layer Pattern

Service Layer Pattern places business logic inside dedicated service classes or files instead of controllers. Controllers become thin and mainly handle request and response operations.

For example, a UserService may contain logic for registration, login, validation, password encryption, and email sending. Controllers only call service methods and return responses. This pattern improves code reuse, readability, testing, and maintainability. It also helps large teams manage business logic in a structured and scalable way.