When to Use Which Design Pattern?: 23 GoF Patterns With Real-World Scenarios Core Java Design Design Patterns java by devs5003 - December 4, 2025December 9, 20250 Last Updated on December 9th, 2025When to Use Which Design Pattern? A Complete Guide to All 23 GoF Patterns Design patterns often confuse developers during interviews, not because they don’t understand the definitions, but because they struggle with WHEN to use WHICH Design Pattern in real-life software design. This article gives scenario-based clarity on each pattern, making you interview-ready. Understanding the definition of a design pattern is easy. Knowing when to use which design pattern is what makes you an architect. This article covers all 23 Gang of Four (GoF) patterns with practical usage, reasoning, and real-world scenarios that help developers answer tough interview questions. If you build Java apps (or any object-oriented systems), this article makes pattern selection easy. No more guesswork. Table of Contents Toggle What to expect from this Article?When to Use Which Design Pattern?CREATIONAL DESIGN PATTERNSSingleton PatternFactory Method PatternAbstract Factory PatternBuilder PatternPrototype PatternSTRUCTURAL DESIGN PATTERNSAdapter PatternWhen to Use?Bridge PatternComposite PatternDecorator PatternFacade PatternFlyweight PatternProxy PatternBEHAVIORAL DESIGN PATTERNSChain of Responsibility PatternCommand PatternInterpreter PatternIterator PatternMediator PatternMemento PatternObserver PatternState PatternStrategy PatternTemplate Method PatternVisitor PatternDetailed Explanations of all 23 GoF’s Design Patterns Top 20 Scenario Based Java Interview QnA: DownloadPractice Set for all 23 GoF’s Design Patterns FAQsConclusionRelated What to expect from this Article? A pattern-by-pattern breakdown: Know when to use which design pattern: when to use, why, and real-life use-cases. A decision-ready mindset: Helps you pick the right pattern under real constraints (performance, structure, scalability, etc.). Interview & architecture ready: Helps in both interviews and real-world system design challenges. Complete Explanations of all Patterns: A reference to all 23 GoF pattern’s detailed explanations with examples. Solved Practice Set: A reference to all 23 GoF pattern’s solved practice set with explanations. When to Use Which Design Pattern? CREATIONAL DESIGN PATTERNS Singleton Pattern When to Use? Use Singleton when you need exactly one instance of a class throughout your system, and this instance must coordinate shared resources. It is ideal when multiple instances can cause data inconsistency, performance overhead, or unexpected behavior.This pattern ensures all parts of your application rely on a single, centralized object. Why? Singleton provides controlled global access and ensures resource sharing is consistent across threads and modules. It avoids unnecessary memory consumption and helps maintain a standard configuration or behavior throughout the application. Real-Time Scenarios A logging service used by multiple microservices sharing the same log formatter and repository. A configuration manager that loads application properties only once and serves them everywhere. A thread pool manager providing a centralized pool of threads to avoid excessive thread creation. Factory Method Pattern When to Use? Use this pattern when object creation must be delegated to subclasses or logic rather than calling constructors directly. It is useful when object types are determined at runtime based on external or dynamic input. This is beneficial when adding new object types without modifying existing client code. Why? Factory Method promotes loose coupling by ensuring the creator class delegates object construction to subclasses. It supports better scalability, testability, and adherence to open/closed principle. Real-Time Scenarios A notification system deciding between SMS, Email, or WhatsApp based on user preference. A database driver loader choosing MySQL, PostgreSQL, or Oracle connection classes based on config. A shape creator in a graphics editor that generates Circle, Rectangle, or Triangle objects dynamically. Abstract Factory Pattern When to Use? Use Abstract Factory when your application needs to create families of related objects but wants to avoid directly instantiating concrete classes. It is perfect when enforcing product consistency is necessary. This helps when multiple product variants share a theme (e.g., UI themes, OS-specific widgets). Why? It groups related objects under a single factory, ensuring compatibility and preventing mismatched combinations of components. Real-Time Scenario Dark Theme vs Light Theme UI toolkit, ensuring all components match (buttons, checkboxes, menus). AWS vs Azure cloud resource factories, ensuring consistent resource creation across vendors. Vehicle part factories—ElectricCarFactory and PetrolCarFactory producing compatible parts only. Builder Pattern When to Use? Use Builder for constructing objects that require many optional fields or multi-step configuration. It helps when constructors become too complex, overloaded, or unclear. This is extremely helpful when building immutable objects. Why? Builder improves readability, enforces step-by-step controlled construction, and avoids telescoping constructors. Real-Time Scenarios Creating complex HTTP requests with headers, params, cookies, and authentication. Building User objects during registration where fields like address and preferences are optional. Creating SQL queries dynamically with multiple conditions and joins. Prototype Pattern When to Use? Use Prototype when object creation is expensive and cloning an existing object is more efficient. It is ideal when objects involve deep copying or heavy initialization logic. Perfect when the system needs duplicate instances with minor variations. Why? Prototype bypasses costly creation processes, promoting performance optimization and reusability. Real-Time Scenarios Cloning document templates for invoices, pay slips, or certificates. Duplicating game characters with similar abilities but minor customizations. Copying graphic objects like shapes in design tools without recreating all properties. STRUCTURAL DESIGN PATTERNS Adapter Pattern When to Use? Use Adapter when your system needs to interact with an incompatible interface without modifying existing code. It’s useful when integrating legacy systems with modern APIs. Works best when you cannot change the target interface. Why? Adapter converts one interface into another, enabling smooth collaboration between otherwise incompatible components. Real-Time Scenarios Integrating an old XML-based API with a new JSON-based REST service. Using third-party payment APIs that require format conversion. Adapting voltage converters conceptually: 220V → 110V device adapter. Bridge Pattern When to Use? Use Bridge when abstraction and implementation must evolve independently. It prevents creating numerous classes when you mix multiple combinations of functionality. Best suited when your system has multiple dimensions of variation. Why? Bridge reduces class explosion by separating what the object does from how it does it. Real-Time Scenarios Shapes (Circle/Square) drawn using APIs (OpenGL/Vulkan) without creating 6 combinations. Remote controls controlling different types of devices (TV, AC, Projector). Payment system separating payment mode (UPI, Card) from platform (Razorpay, Stripe). Composite Pattern When to Use? Use Composite when you need to represent hierarchies where individual items and groups should be treated uniformly. Perfect when operations must be applied to both leaf and composite objects seamlessly. Why? Composite simplifies tree structure management by letting clients treat both single objects and groups the same way. Real-Time Scenarios File Explorer: File and Folder handled through one interface. Organizational Hierarchy: CEO → Managers → Employees. UI components: panels containing buttons, text fields, and nested containers. Decorator Pattern When to Use? Use Decorator when you want to add new features dynamically without altering the original class. Ideal when inheritance becomes too rigid or leads to too many subclasses. Why? Decorator provides flexible runtime extension by wrapping objects with additional behavior. Real-Time Scenarios Coffee shop system: add milk, chocolate, foam, caramel on top of base coffee. Spring’s HandlerInterceptor adding logging/authentication layers. Adding encryption, compression, or caching to streams dynamically. Facade Pattern When to Use? Use Facade when you want to provide a simplified interface to a complex subsystem. Ideal when clients must be shielded from heavy initialization and dependencies. Why? Facade reduces complexity, improves readability, and creates a single entry point to multiple components. Real-Time Scenarios Hotel booking hides allocation, payment, and housekeeping APIs. Spring Boot starter packages simplify complex library configurations. A video conversion utility hiding codec handling and file operations. Flyweight Pattern When to Use? Use Flyweight when many objects share common internal data, and memory consumption becomes a concern. Perfect when object count may reach thousands or millions. Why? Flyweight reduces memory footprint by reusing shared intrinsic state and separating extrinsic state. Real-Time Scenarios Text editors storing formatting styles as shared objects. Browser caching icons, emojis, or fonts as shared reusable resources. Game engines reusing sprite textures across multiple objects. Proxy Pattern When to Use? Use Proxy when controlling access to an object is essential: security, lazy loading, caching, or remote invocation. Useful when working with large or remote objects. Why? Proxy acts as a gateway that adds extra behavior before delegating to the real object. Real-Time Scenarios Hibernate’s lazy-loading proxy for database entities. Authentication proxy checking permissions before accessing sensitive resources. Remote proxy connecting clients to remote services via RMI or gRPC. BEHAVIORAL DESIGN PATTERNS Chain of Responsibility Pattern When to Use? Use this pattern when requests must pass through a series of handlers, each deciding whether to process or pass it onward. Ideal when avoiding nested if-else chains. Why? It decouples sender from receivers and makes request processing flexible and maintainable. Real-Time Scenarios Servlet filters: authentication → authorization → logging → validation. Loan approval: clerk → manager → director approvals. Customer complaints passed through various support tiers (L1 → L2 → L3). Command Pattern When to Use? Use Command when you need to encapsulate actions as objects for flexible execution strategies. Supports undo/redo operations, command queues, or transaction batching. Why? It decouples invoker from receiver, allowing actions to be stored, reused, or reversed. Real-Time Scenarios Text editors performing undo/redo on formatting operations. Queueing commands in task schedulers or job systems. Smart home automation defining commands like “Turn on AC,” “Dim Lights,” etc. Interpreter Pattern When to Use? Use Interpreter when building grammar-based processing—mini languages, rules engines, or expression evaluators. Best for simple grammars, not full-blown programming languages. Why? It enables defining rules and interpreting custom expressions systematically. Real-Time Scenarios SQL-like filters for search systems (e.g., price > 100 AND category = ‘books’). Chatbot rule definitions like “if user says X then reply Y.” Regex engines internally interpreting expression patterns. Iterator Pattern When to Use? Use Iterator when you need a standard mechanism to traverse a collection without exposing its internal structure. Perfect when collections change but traversal logic should remain consistent. Why? Iterator simplifies looping and enables multiple traversal strategies independently. Real-Time Scenarios Java iterators on lists, sets, maps. File system iterating over files and directories. Iterating over database cursor results. Mediator Pattern When to Use? Use Mediator when communication between components becomes complex, chaotic, or tightly coupled. The mediator centralizes interactions and simplifies component relationships. Why? It promotes loose coupling and simplifies system maintenance. Real-Time Scenarios Chatroom controlling interactions among multiple users. Air traffic control tower coordinating airplanes. UI dialog box coordinating text fields, buttons, and validation. Memento Pattern When to Use? Use Memento when you need to store and restore object states without violating encapsulation. Ideal for undo/rollback features. Why? It allows maintaining historical states separately from core objects. Real-Time Scenarios Code editors storing snapshots for undo operations. Game state checkpoints. Form data recovery after unexpected crashes. Observer Pattern When to Use? Use Observer when one object must notify many dependents about state changes. Ideal for real-time data updates. Why? It enables event-driven systems with decoupled publishers and subscribers. Real-Time Scenarios Stock price updates notifying dashboards. Weather station broadcasting temperature updates. E-commerce order tracking updates. State Pattern When to Use? Use State when an object’s behavior varies based on internal state transitions. Avoids large conditional blocks by encapsulating state-specific logic. Why? Provides cleaner modeling of lifecycle-driven behavior. Real-Time Scenarios Order lifecycle: Placed → Packed → Shipped → Delivered. ATM behavior: CardInserted, OutOfCash, Idle. Media player: Play, Pause, Stop states. Strategy Pattern When to Use? Use Strategy when multiple algorithms can be chosen at runtime. Keep algorithms independent, interchangeable, and easily extendable. Why? Promotes open/closed principle and allows runtime flexibility. Real-Time Scenarios Compression strategies: ZIP, GZIP, RAR. Payment algorithms: UPI, NetBanking, Card. Sorting strategies: QuickSort, MergeSort, HeapSort. Template Method Pattern When to Use? Use Template Method when your algorithm structure is fixed but specific steps may vary across implementations. This helps enforce consistent workflows. Why? Allows common logic reuse while letting subclasses override specific steps. Real-Time Scenarios Online order processing: validate → pay → ship (different gateways override payment step). Data parsing templates: CSV vs JSON vs XML parsing. Document approval workflows across departments. Visitor Pattern When to Use? Use Visitor when new operations must be frequently added to object structures without modifying their classes. Ideal for extending behavior. Why? Visitor separates algorithms from object structures, keeping both clean and scalable. Real-Time Scenarios Compiler visitors: type checking, optimization, code generation. PDF generation visiting objects like text, tables, images. Data export tool generating CSV, XML, JSON using visitors. Detailed Explanations of all 23 GoF’s Design Patterns Kindly visit separate series of articles: ‘Design Patterns in Java‘ Top 20 Scenario Based Java Interview QnA: Download 👉 Download TOP 20 Java Design Pattern’s Scenario Based Interview QnA📥 (File size: ~5 MB | Format: PDF | No sign-up required) Practice Set for all 23 GoF’s Design Patterns GoF’s Design Patterns Practice Test Download Java Design Patterns Solved Interview Questions PDF FAQs Q#1. Your payment engine must support multiple payment methods (UPI, Credit Card, NetBanking, Wallet). The choice must be decided at runtime, and new payment methods should be easily plug-and-play without modifying core logic.Which design pattern should you choose and why? Ans. Recommended Pattern: Factory Method + Strategy (sometimes combined) Why Factory Method? Payment object creation depends on runtime user choice. New payment methods can be added by extending a creator class without touching existing code (OCP). Scenario Benefit: PaymentFactory.create(“UPI”) returns appropriate object. Avoids if-else or switch-case object creation. Why not Builder? Because we’re not assembling complex objects; we’re selecting object type. Why not Abstract Factory? We’re not producing families of related payment objects. Q#2. Let’s Consider 2 Shapes: Circle, Rectangleand 3 Rendering Modes: OpenGL, DirectX, SVG Without patterns, you’d need multiple number of classes. How to avoid this? Ans. Recommended Pattern: Bridge Pattern Why? Separates Shape abstraction from Rendering implementation Each can grow independently Not Adapter: No interface incompatibility. Not Composite: No tree structure. Q#3. A reporting engine must construct highly customizable reports. Users can choose columns, filters, groups, exports, themes, logos, etc. Some fields are optional. Which pattern should you use? Ans. Recommended Pattern: Builder Pattern Why? Many optional attributes Object creation happens step-by-step Makes code readable Supports immutability Scenario Benefit: Report report = ReportBuilder() .withHeader() .withFooter() .withFilters(...) .withExportOption(...) .build(); Why not Prototype? Because the problem is not expensive cloning. Why not Factory? Factory returns complete objects, not partially constructed ones. Q#4. A game world has millions of trees. Each tree shares the same texture, color, shape, but different x,y coordinates. Which pattern helps? Ans. Recommended Pattern: Flyweight Pattern Why? Shared intrinsic data (texture, mesh) Extrinsic data (location) stored externally Massive memory savings Not Prototype: Cloning doesn’t solve memory duplication. Not Decorator: Adds behavior, not memory optimization. Q#5. You want each request to go through steps: Authentication → Authorization → Logging → Rate Limiting. Each handler may choose to process or pass it on. Which pattern helps? Ans. Recommended Pattern: Chain of Responsibility Why? Handlers are independent Order is configurable Avoids nested if-else statements Not Observer: no broadcasting. Not Command: no encapsulated actions required. Conclusion If you want to crack interviews confidently, understanding WHEN to use a design pattern is far more valuable than memorizing definitions.Use this resource as your practical reference whenever you face real architecture design questions. Sources Used Gang of Four: Design Patterns (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) Oracle Java Documentation: https://docs.oracle.com/javase/ Related