Facade Pattern
Overview
Starting a movie requires lowering the screen, dimming the lights and starting the player. If every screen knows those devices and their order, the same preparation code spreads across callers.
Facade puts a simpler entry point in front of a subsystem. A caller asks to start a movie, and the facade coordinates the operations needed for that task.
UML
The caller uses MovieNight. MovieNight holds Screen, Lights and Player objects and calls them in the order needed to start or stop.
History
GoF cataloged Facade as a structural pattern in Design Patterns in 1994. It offers a higher-level interface that makes a subsystem easier to use.1
Why use it?
Callers need neither each device name nor the preparation sequence. A sequence change belongs in this entry point rather than in every screen.
A facade is an entry point, not a dumping ground. Keep business rules with their owning modules, and preserve lower-level access where callers genuinely need finer control.
Example
One method coordinates movie preparation. The device stand-ins return operation names instead of controlling hardware.
using System;
using System.Collections.Generic;
using System.Linq;
var night = new MovieNight(new Screen(), new Lights(), new Player());
Console.WriteLine(night.Start("Moon"));
sealed class Screen
{
public string Lower() => "screen down";
public string Raise() => "screen up";
}
sealed class Lights
{
public string Dim() => "lights dim";
public string Restore() => "lights normal";
}
sealed class Player
{
public string Play(string title) => "play " + title;
public string Stop() => "player stop";
}
sealed class MovieNight(Screen screen, Lights lights, Player player)
{
public string Start(string title) =>
string.Join(" -> ", screen.Lower(), lights.Dim(), player.Play(title));
public string Stop() =>
string.Join(" -> ", player.Stop(), lights.Restore(), screen.Raise());
}
screen down -> lights dim -> play MoonThe result shows the order owned by Start(). Device behavior and coordination remain separate responsibilities.
An extended example
Add the matching stop operation and call both through the facade.
using System;
using System.Collections.Generic;
using System.Linq;
var night = new MovieNight(new Screen(), new Lights(), new Player());
Console.WriteLine(night.Start("Moon"));
Console.WriteLine(night.Stop());
sealed class Screen
{
public string Lower() => "screen down";
public string Raise() => "screen up";
}
sealed class Lights
{
public string Dim() => "lights dim";
public string Restore() => "lights normal";
}
sealed class Player
{
public string Play(string title) => "play " + title;
public string Stop() => "player stop";
}
sealed class MovieNight(Screen screen, Lights lights, Player player)
{
public string Start(string title) =>
string.Join(" -> ", screen.Lower(), lights.Dim(), player.Play(title));
public string Stop() =>
string.Join(" -> ", player.Stop(), lights.Restore(), screen.Raise());
}
screen down -> lights dim -> play Moon
player stop -> lights normal -> screen upA single method does not make several device operations atomic. Real devices need an explicit response to partial failure. The separate Query Facade article applies this entry-point idea to assembling query results.
Related reading
Each example is a separate .NET 10 console program.
Footnotes
- Gamma, Helm, Johnson, Vlissides. Design Patterns (1994). Publisher record. Structural patterns, Facade. ↩