Skip to content

Structural Patterns — Detailed#

Adapter — make an incompatible interface fit#

classDiagram
  class Client
  class Target {
    <<interface>>
    +request()
  }
  class Adapter {
    -adaptee: Adaptee
    +request()
  }
  class Adaptee {
    +specificRequest()
  }
  Client --> Target
  Target <|.. Adapter
  Adapter --> Adaptee : delegates

Wraps an existing class so it conforms to a different interface. Bridges to legacy / third-party APIs.


Decorator — wrap with extra behaviour without subclassing#

classDiagram
  class Component {
    <<interface>>
    +operation()
  }
  class ConcreteComponent
  class Decorator {
    -wrapped: Component
    +operation()
  }
  class LoggingDecorator
  class CachingDecorator
  Component <|.. ConcreteComponent
  Component <|.. Decorator
  Decorator <|-- LoggingDecorator
  Decorator <|-- CachingDecorator
  Decorator --> Component : wraps

Each decorator adds a behaviour and forwards to the wrapped instance. Stackable. Java BufferedReader(new FileReader(...)) is the canonical example.


Facade — one simplified interface in front of a subsystem#

classDiagram
  class Client
  class Facade {
    +simple()
  }
  class SubA
  class SubB
  class SubC
  Client --> Facade
  Facade --> SubA
  Facade --> SubB
  Facade --> SubC

The subsystem stays open for power users; the Facade exposes the 80% workflow.


Proxy — same interface, controls access#

classDiagram
  class Subject {
    <<interface>>
    +request()
  }
  class RealSubject
  class Proxy {
    -real: RealSubject
    +request()
  }
  Subject <|.. RealSubject
  Subject <|.. Proxy
  Proxy --> RealSubject

Common flavours:

Proxy type Adds
Virtual proxy lazy instantiation of expensive objects
Protection proxy access checks / RBAC
Remote proxy RPC client stub
Caching proxy memoises responses
Smart proxy reference counting, logging

Composite — treat tree of objects as one#

classDiagram
  class Component {
    <<interface>>
    +render()
  }
  class Leaf
  class Container {
    -children: Component[]
    +add(Component)
    +render()
  }
  Component <|.. Leaf
  Component <|.. Container
  Container o--> Component

UI widgets, file systems, org charts, ASTs.


Bridge — separate abstraction from implementation#

classDiagram
  class Abstraction {
    -impl: Implementor
  }
  class RefinedAbstraction
  class Implementor {
    <<interface>>
  }
  class ImplA
  class ImplB
  Abstraction <|-- RefinedAbstraction
  Implementor <|.. ImplA
  Implementor <|.. ImplB
  Abstraction --> Implementor

Use when both the abstraction and the implementation can vary independently (e.g. shapes × rendering backends).


Flyweight — share intrinsic state across many small objects#

When you have millions of small objects with mostly-identical state, share the intrinsic bits (font glyphs, terrain tiles) and keep only extrinsic state (position, rotation) per instance.

Where these show up in this site#

  • API gateway / proxy: Proxy pattern.
  • Distributed cache (cache-aside): Caching Proxy.
  • CDN: Caching Proxy + Reverse Proxy.
  • Logger framework: Decorator (adding format/level/filter chains).
  • Online whiteboard / Google Docs: Composite for nested shapes / block trees.

Glossary & fundamentals#

Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.

Tag Concept What it is Page
HLD CDN edge caching for static assets cdn
HLD API gateway / BFF single ingress, auth, rate limit, routing api-gateway
HLD Cache strategies cache-aside, read/write-through, eviction caching-strategies
LLD OOP pillars encapsulation, abstraction, inheritance, polymorphism oop-pillars
LLD Structural patterns Adapter, Decorator, Facade, Proxy, Composite structural-patterns