The Facade pattern provides a simplified interface to a larger, more complex system by compositing subsystems.
✅ Single Responsibility Principle (SRP)
✅ Open/Closed Principle (OCP)
✅ Liskov Substitution Principle (LSP) / Interface Segregation Principle (ISP)
✅ Dependency Inversion Principle (DIP)
Wrapping behaviour is not recommended via inheritance, even though it doesn’t require wrapping multiple subsystems or wrapping at runtime, but introduces unnecessary coupling.
// Subsystems
class Lights {
turnOn() { console.log("Lights are on."); }
turnOff() { console.log("Lights are off."); }
}
class Music {
play() { console.log("Playing music."); }
stop() { console.log("Music stopped."); }
}
// Facade
class HomeAutomation {
private lights: Lights;
private music: Music;
constructor() {
// The subsystems can either be encapsulated or use DI injection.
// - Encapsulation: for fixed type cohesion and simplicity
// - DI: for testability and runtime flexibility
this.lights = new Lights();
this.music = new Music();
}
public arriveHome() {
this.lights.turnOn()
this.music.play();
}
public leaveHome() {
this.lights.turnOff();
this.music.stop();
}
}
// Client
const home = new HomeAutomation();
home.arriveHome();
To hide the subsystems’ API from the client and prevent names conflict on multiple subsystems, so it use Explicit Embedding.
// Subsystems
type Lights struct{}
func (l *Lights) TurnOn() { fmt.Println("Lights are on.") }
func (l *Lights) TurnOff() { fmt.Println("Lights are off.") }
type Music struct{}
func (m *Music) Play() { fmt.Println("Playing music.") }
func (m *Music) Stop() { fmt.Println("Music stopped.") }
// Facade
type HomeAutomation struct {
lights *Lights
music *Music
}
func NewHomeAutomation() *HomeAutomation {
// The subsystems can either be encapsulated or use DI injection.
// - Encapsulation: for fixed type cohesion and simplicity
// - DI: for testability and runtime flexibility
return &HomeAutomation{
lights: &Lights{},
music: &Music{},
}
}
func (h *HomeAutomation) ArriveHome() {
h.lights.TurnOn()
h.music.Play()
}
func (h *HomeAutomation) LeaveHome() {
h.lights.TurnOff()
h.music.Stop()
}
// Client
func main() {
home := NewHomeAutomation()
home.ArriveHome()
}