Bird
Raised Fist0
LLDsystem_design~15 mins

When to use which structural pattern in LLD - Deep Dive

Choose your learning style10 modes available
Overview - When to use which structural pattern
What is it?
Structural patterns are ways to organize parts of a software system so they fit together well. They help manage how objects and classes connect and work as a group. This topic explains when to choose each pattern based on the problem you want to solve. It guides you to pick the right structure for clear, flexible, and maintainable designs.
Why it matters
Without knowing when to use each structural pattern, software can become messy and hard to change. This leads to bugs, slow development, and unhappy users. Using the right pattern saves time and effort by making systems easier to understand and extend. It helps teams build software that lasts and adapts to new needs.
Where it fits
Before this, you should understand basic object-oriented concepts like classes, objects, and interfaces. Knowing common design patterns like creational and behavioral patterns helps too. After this, you can learn how to combine patterns for complex systems and how to apply them in real projects.
Mental Model
Core Idea
Choosing the right structural pattern is like picking the best way to connect building blocks so the whole system stands strong and can grow easily.
Think of it like...
Imagine building a house with different types of connectors: nails, screws, or brackets. Each connector fits a different part and purpose. Using the wrong connector can make the house weak or hard to fix later. Structural patterns are these connectors for software parts.
Structural Patterns Overview
┌───────────────┐
│ Client Code   │
└──────┬────────┘
       │ uses
┌──────▼────────┐
│ Structural    │
│ Pattern       │
│ (e.g., Adapter│
│ Composite)    │
└──────┬────────┘
       │ connects
┌──────▼────────┐
│ Objects &     │
│ Classes       │
└───────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding structural patterns basics
🤔
Concept: Structural patterns organize relationships between classes and objects to form larger structures.
Structural patterns focus on how to assemble objects and classes to create bigger structures. They help manage complexity by defining clear ways parts fit together. Examples include Adapter, Bridge, Composite, Decorator, Facade, Flyweight, and Proxy.
Result
You know that structural patterns solve problems about object relationships and system organization.
Understanding that structural patterns are about connections helps you see why they improve system flexibility and clarity.
2
FoundationCommon structural patterns overview
🤔
Concept: Learn the main structural patterns and their basic purposes.
Adapter changes one interface to another so classes can work together. Bridge separates abstraction from implementation to vary them independently. Composite lets you treat groups and single objects the same. Decorator adds behavior dynamically. Facade simplifies complex systems. Flyweight shares objects to save memory. Proxy controls access to objects.
Result
You can name key structural patterns and their simple roles.
Knowing the purpose of each pattern prepares you to match them to real problems.
3
IntermediateWhen to use Adapter pattern
🤔Before reading on: do you think Adapter is best when interfaces differ or when adding new features? Commit to your answer.
Concept: Adapter is used when you want to make incompatible interfaces work together without changing their code.
Use Adapter when you have existing classes with different interfaces but need them to cooperate. For example, if a new system expects a certain interface but you have legacy code with another, Adapter wraps the old code to match the new interface.
Result
You can connect incompatible parts without rewriting them.
Knowing Adapter helps you integrate old and new code smoothly, saving time and reducing errors.
4
IntermediateWhen to use Composite pattern
🤔Before reading on: do you think Composite is for grouping objects or for simplifying interfaces? Commit to your answer.
Concept: Composite lets you treat individual objects and groups of objects uniformly.
Use Composite when you have tree-like structures where leaves and branches should be handled the same way. For example, a file system where files and folders can be processed with the same methods.
Result
You simplify code by handling single and grouped objects identically.
Understanding Composite reduces code complexity when dealing with hierarchical data.
5
IntermediateWhen to use Decorator pattern
🤔Before reading on: do you think Decorator adds features at compile-time or runtime? Commit to your answer.
Concept: Decorator adds responsibilities to objects dynamically without changing their class.
Use Decorator when you want to add features to objects on the fly, like adding scrollbars to windows or adding filters to data streams. It wraps the original object and adds new behavior.
Result
You can extend object behavior flexibly and transparently.
Knowing Decorator helps you avoid subclass explosion and keep code flexible.
6
AdvancedChoosing Facade for system simplicity
🤔Before reading on: do you think Facade hides complexity or adds new features? Commit to your answer.
Concept: Facade provides a simple interface to a complex subsystem.
Use Facade when you want to hide complicated internals from clients and offer a clean, easy-to-use interface. For example, a library that wraps many classes behind one simple API.
Result
Clients interact with a simpler interface, reducing learning and errors.
Understanding Facade improves system usability and reduces coupling.
7
ExpertBalancing Flyweight and Proxy patterns
🤔Before reading on: do you think Flyweight and Proxy both save resources or serve different goals? Commit to your answer.
Concept: Flyweight shares objects to save memory; Proxy controls access and can add lazy loading or security.
Use Flyweight when many similar objects exist and you want to share common parts to reduce memory. Use Proxy when you want to control access, delay creation, or add extra actions. Sometimes they overlap but serve distinct purposes.
Result
You optimize resource use and control object access effectively.
Knowing the subtle difference between Flyweight and Proxy helps avoid misuse and improves system performance.
Under the Hood
Structural patterns work by defining clear roles and relationships between objects and classes. They use techniques like wrapping (Decorator, Proxy), grouping (Composite), interface translation (Adapter), and abstraction separation (Bridge). These patterns rely on object references and delegation to connect parts without tight coupling.
Why designed this way?
They were designed to solve common problems in software design: complexity, rigidity, and code duplication. By separating concerns and promoting reuse, these patterns make systems easier to maintain and extend. Alternatives like monolithic designs or deep inheritance hierarchies were harder to change and understand.
Structural Pattern Mechanism
┌───────────────┐
│ Client        │
└──────┬────────┘
       │ calls
┌──────▼────────┐
│ Pattern Layer │
│ (Adapter,     │
│ Decorator,    │
│ Composite...) │
└──────┬────────┘
       │ delegates
┌──────▼────────┐
│ Real Objects  │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Is Adapter used to add new features or just to match interfaces? Commit yes or no.
Common Belief:Adapter is for adding new features to existing classes.
Tap to reveal reality
Reality:Adapter only changes interfaces to make incompatible classes work together; it does not add new features.
Why it matters:Misusing Adapter to add features leads to confusing code and violates single responsibility, making maintenance harder.
Quick: Does Composite pattern only work for two-level hierarchies? Commit yes or no.
Common Belief:Composite is only for simple, two-level object groups.
Tap to reveal reality
Reality:Composite supports any depth of tree-like structures, allowing uniform treatment of nested groups.
Why it matters:Limiting Composite to shallow hierarchies prevents leveraging its full power for complex data structures.
Quick: Can Decorator replace subclassing in all cases? Commit yes or no.
Common Belief:Decorator can always replace subclassing for adding behavior.
Tap to reveal reality
Reality:Decorator is great for dynamic behavior addition, but subclassing is still useful for static, compile-time extensions.
Why it matters:Overusing Decorator can complicate runtime behavior and debugging if static inheritance would suffice.
Quick: Are Flyweight and Proxy patterns interchangeable? Commit yes or no.
Common Belief:Flyweight and Proxy do the same thing by sharing objects.
Tap to reveal reality
Reality:Flyweight shares data to save memory; Proxy controls access and can add extra logic without sharing.
Why it matters:Confusing these leads to wrong pattern use, causing performance or security issues.
Expert Zone
1
Some structural patterns combine naturally, like using Facade to wrap a Composite structure for simpler client access.
2
Choosing between Decorator and Proxy can be subtle; Decorator focuses on behavior extension, Proxy on access control and lazy loading.
3
Bridge pattern is often overlooked but crucial when you want to vary abstraction and implementation independently, avoiding class explosion.
When NOT to use
Avoid structural patterns when simple direct relationships suffice; for example, don't use Composite for flat lists or Adapter when interfaces already match. Instead, use simpler designs or behavioral patterns when the problem is about actions, not structure.
Production Patterns
In real systems, Facade is common to hide complex subsystems like databases or APIs. Composite is used in UI frameworks for nested components. Decorator appears in stream processing or UI enhancements. Adapter helps integrate legacy code or third-party libraries. Flyweight is used in graphics or text rendering to save memory.
Connections
Modular Architecture
Structural patterns build the internal connections that modular architecture organizes at a higher level.
Understanding structural patterns helps design modules that are loosely coupled and easy to replace or upgrade.
Electrical Circuit Design
Both involve connecting components with specific connectors to achieve desired functions and flexibility.
Seeing software patterns like circuit components clarifies why certain connections improve system stability and adaptability.
Supply Chain Management
Structural patterns organize parts like supply chains organize goods flow, ensuring smooth operation and scalability.
Knowing this helps appreciate the importance of clear interfaces and controlled access in complex systems.
Common Pitfalls
#1Using Adapter to add new features instead of just matching interfaces.
Wrong approach:class Adapter { newFeature() { /* added here */ } existingMethod() { /* adapts interface */ } }
Correct approach:class Adapter { existingMethod() { /* adapts interface only */ } } // Add new features via Decorator or subclassing instead
Root cause:Confusing Adapter's purpose leads to mixing interface adaptation with feature extension.
#2Treating Composite as only for shallow hierarchies.
Wrong approach:if (node.level > 2) throw Error('Composite too deep');
Correct approach:Allow Composite to handle any depth by recursive calls on children.
Root cause:Misunderstanding Composite's recursive nature limits its usefulness.
#3Overusing Decorator when subclassing would be simpler.
Wrong approach:let decorated = new Decorator(new Decorator(new Base())); // many layers at runtime
Correct approach:class ExtendedBase extends Base { /* static extension */ }
Root cause:Not recognizing when static inheritance is clearer and easier to maintain.
Key Takeaways
Structural patterns help organize software parts to work together clearly and flexibly.
Choosing the right pattern depends on the problem: adapting interfaces, grouping objects, adding behavior, or simplifying access.
Misusing patterns leads to complex, hard-to-maintain code, so understanding their purpose is crucial.
Advanced use involves combining patterns and knowing subtle differences like between Flyweight and Proxy.
Real-world systems rely heavily on these patterns to build scalable, maintainable software.

Practice

(1/5)
1. Which structural pattern is best suited for representing part-whole hierarchies like folders and files in a system?
easy
A. Facade pattern
B. Composite pattern
C. Proxy pattern
D. Decorator pattern

Solution

  1. Step 1: Understand the problem context

    Part-whole hierarchies like folders and files form tree structures where each node can be a composite or a leaf.
  2. Step 2: Match the pattern to the structure

    The Composite pattern is designed to treat individual objects and compositions uniformly, perfect for tree-like structures.
  3. Final Answer:

    Composite pattern -> Option B
  4. Quick Check:

    Tree structures = Composite pattern [OK]
Hint: Tree or hierarchy? Use Composite pattern [OK]
Common Mistakes:
  • Confusing Decorator with Composite
  • Using Proxy for hierarchy management
  • Choosing Facade for internal structure
2. Which pattern should you use if you want to add responsibilities to objects dynamically without changing their class?
easy
A. Proxy pattern
B. Facade pattern
C. Composite pattern
D. Decorator pattern

Solution

  1. Step 1: Identify the need to add features dynamically

    When you want to add new behavior to objects at runtime without altering their class, you need a flexible pattern.
  2. Step 2: Select the pattern that wraps objects

    The Decorator pattern wraps objects to add responsibilities dynamically, without changing the original class.
  3. Final Answer:

    Decorator pattern -> Option D
  4. Quick Check:

    Add features dynamically = Decorator [OK]
Hint: Add features on the fly? Use Decorator [OK]
Common Mistakes:
  • Choosing Proxy instead of Decorator
  • Using Facade to add features
  • Confusing Composite with Decorator
3. Consider a system where you want to control access to a resource and add lazy loading. Which structural pattern fits best?
class ResourceProxy {
  constructor() {
    this.resource = null;
  }
  access() {
    if (!this.resource) {
      this.resource = new RealResource();
    }
    return this.resource;
  }
}
medium
A. Proxy pattern
B. Decorator pattern
C. Composite pattern
D. Facade pattern

Solution

  1. Step 1: Analyze the code behavior

    The code delays creating the real resource until it is accessed, controlling access and adding lazy loading.
  2. Step 2: Identify the matching pattern

    This behavior matches the Proxy pattern, which controls access to another object and can add lazy initialization.
  3. Final Answer:

    Proxy pattern -> Option A
  4. Quick Check:

    Control access + lazy load = Proxy [OK]
Hint: Control access or lazy load? Use Proxy [OK]
Common Mistakes:
  • Confusing Proxy with Decorator
  • Using Facade for access control
  • Choosing Composite for resource control
4. You have a complex subsystem with many classes. You want to provide a simple interface to clients. Which pattern should you use? A developer wrote this code but clients still see complex calls:
class ComplexSystem {
  operationA() {}
  operationB() {}
  operationC() {}
}

class SimpleInterface {
  constructor() {
    this.system = new ComplexSystem();
  }
  simpleOperation() {
    this.system.operationA();
    this.system.operationB();
    this.system.operationC();
  }
}
What is the likely mistake?
medium
A. They did not hide the ComplexSystem instance properly
B. They used Proxy instead of Facade
C. They used Composite instead of Facade
D. They forgot to add Decorator to SimpleInterface

Solution

  1. Step 1: Understand Facade pattern purpose

    Facade provides a simple interface hiding complex subsystem details from clients.
  2. Step 2: Identify the mistake in code usage

    If clients still see complex calls, likely the ComplexSystem instance is exposed or clients bypass the Facade.
  3. Final Answer:

    They did not hide the ComplexSystem instance properly -> Option A
  4. Quick Check:

    Facade hides complexity = hide subsystem [OK]
Hint: Facade hides complexity; don't expose subsystem [OK]
Common Mistakes:
  • Confusing Proxy with Facade
  • Exposing subsystem objects to clients
  • Using Decorator to simplify interface
5. You are designing a graphic editor. You want to represent shapes that can be simple (circle, square) or groups of shapes. You also want to add features like border color dynamically and control access to some shapes. Which combination of structural patterns should you use?
hard
A. Facade for groups, Proxy for features, Composite for access control
B. Decorator for groups, Composite for features, Facade for access control
C. Composite for groups, Decorator for features, Proxy for access control
D. Proxy for groups, Facade for features, Decorator for access control

Solution

  1. Step 1: Match patterns to requirements

    Groups of shapes form tree structures best handled by Composite. Adding features dynamically fits Decorator. Controlling access fits Proxy.
  2. Step 2: Combine patterns correctly

    Use Composite for shape groups, Decorator to add border color dynamically, and Proxy to control access to shapes.
  3. Final Answer:

    Composite for groups, Decorator for features, Proxy for access control -> Option C
  4. Quick Check:

    Groups=Composite, Features=Decorator, Access=Proxy [OK]
Hint: Groups=Composite, Features=Decorator, Access=Proxy [OK]
Common Mistakes:
  • Mixing Facade with group representation
  • Using Proxy for adding features
  • Confusing Decorator with access control
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard