Facade Pattern

Facade Pattern

Provide a unified interface to a set of interfaces in a subsystem — making the subsystem easier to use without restricting access to it.

Intent

The Facade defines a simpler, higher-level interface (the Facade class) over a complex subsystem. It does not convert interfaces from one shape to another — that is Adapter. It does not separate abstraction from implementation hierarchies — that is Bridge. The Facade simplifies. Clients that need the simple path use the Facade; advanced clients who need full subsystem power can bypass it and call subsystem classes directly. This reduces coupling between clients and subsystem internals: the client depends only on the Facade, not on every class in the subsystem.

When NOT to Use

  • Clients genuinely need access to all subsystem details — a Facade would frustrate them with an incomplete interface that forces them to bypass it anyway
  • The subsystem is already simple — adding a Facade is unnecessary layering with no coupling benefit
  • You need to convert one interface to another specific existing interface — use Adapter-Pattern instead (Adapter converts; Facade simplifies)

When to Use

  • A complex subsystem has a simpler default usage path for most clients
  • You want to layer a subsystem: expose a simple path (Facade) while keeping advanced access available for clients that need it
  • Reducing coupling between clients and the subsystem internals is a priority

How It Works

Participants: Facade (unified high-level API class), Subsystem classes (many, complex, uncoordinated), Client (uses only the Facade for the common path).

The Facade knows which subsystem classes to invoke and in what order. The subsystem classes do the real work; the Facade delegates. Clients call the Facade methods and are shielded from knowing which subsystem classes exist or how they coordinate. Advanced clients can still call subsystem classes directly — the Facade does not lock them out.

Class Diagram

classDiagram
    class Facade {
        -subsystemA : SubsystemA
        -subsystemB : SubsystemB
        -subsystemC : SubsystemC
        +operationX()
        +operationY()
    }
    class SubsystemA {
        +methodA1()
        +methodA2()
    }
    class SubsystemB {
        +methodB1()
    }
    class SubsystemC {
        +methodC1()
        +methodC2()
    }
    class Client
    Client --> Facade : simplified API
    Facade o-- SubsystemA : delegates
    Facade o-- SubsystemB : delegates
    Facade o-- SubsystemC : delegates

TypeScript Example

// Facade — TypeScript
// Source: GoF Design Patterns, p.185
 
class AudioDecoder { decode(file: string) { /* ... */ } }
class VideoDecoder { decode(file: string) { /* ... */ } }
class Renderer      { render(audio: unknown, video: unknown) { /* ... */ } }
 
class MediaPlayer {  // Facade
  private audio = new AudioDecoder();
  private video = new VideoDecoder();
  private renderer = new Renderer();
 
  play(file: string) {
    const a = this.audio.decode(file);
    const v = this.video.decode(file);
    this.renderer.render(a, v);
  }
}
 
// Client uses only MediaPlayer — unaware of AudioDecoder, VideoDecoder, Renderer
const player = new MediaPlayer();
player.play("movie.mp4");

Java Example

// Facade — Java
// Source: GoF Design Patterns, p.185
class AudioDecoder { void decode(String f) { /* ... */ } }
class VideoDecoder { void decode(String f) { /* ... */ } }
class Renderer     { void render(Object a, Object v) { /* ... */ } }
 
class MediaPlayer {  // Facade
    private AudioDecoder audio = new AudioDecoder();
    private VideoDecoder video = new VideoDecoder();
    private Renderer renderer = new Renderer();
 
    public void play(String file) {
        audio.decode(file);
        video.decode(file);
        renderer.render(null, null);
    }
}
 
// Client only depends on MediaPlayer

Lineage Forward (Phase 8 Success Criterion 4)

Facade → Anti-Corruption Layer lineage:

The Facade pattern is the structural ancestor of the Anti-Corruption-Layer-Pattern (created Phase 10). An ACL provides a Facade-like simplified interface between two Bounded Contexts (see Bounded-Context), adding translation and corruption-prevention semantics. Where Facade simplifies access to a subsystem within the same domain, ACL defends a domain model against corruption from a foreign model. The lineage continues: Facade → ACL → Strangler-Fig-Pattern (Phase 14) → API-Gateway-Pattern.

PatternRelationship
Adapter-PatternAdapter converts interface A to interface B that a client already expects; Facade defines a new simpler interface
Bridge-PatternBridge separates abstraction from implementation hierarchies; Facade simplifies access to a subsystem
Anti-Corruption-Layer-PatternDDD pattern that extends Facade with translation and domain corruption prevention (created Phase 10)
Mediator-PatternMediator reduces coupling between peer objects; Facade reduces coupling between client and subsystem (created Phase 9)
  • Micro-Frontends — The shell/host application in a micro-frontends composition acts as a Facade; it presents a unified product surface while hiding the compositional complexity of independently deployed micro-frontends.
  • REST-API-Design — REST API resource models often act as facades over complex domain models, projecting a simplified surface to clients

Sources

  • Gamma, Helm, Johnson, Vlissides — Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1994, p.185

Notes that link here: GoF-Patterns-MOC