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 |