Facade Pattern
Introduction
The Facade pattern is a structural design pattern that provides a simplified interface to a complex system of classes, library, or framework. This pattern is particularly useful for providing a simple interface to a complex subsystem.
Purpose
- To provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
- To decouple a client implementation from the complex subsystem.
Use Cases
- When you want to provide a simple or reduced interface to a complex subsystem.
- When there are many dependencies between clients and the implementation classes of an abstraction.
Advantages/Disadvantages
Advantages:
- Simplifies the interface to complex systems.
- Reduces dependencies on outside code.
- Helps to segregate layers and components in a system.
Disadvantages:
- A facade can become a god object coupled to all classes of an app.
Implementation in JavaScript
class Subsystem1 {
operation1() {
return 'Subsystem1: Ready!\n';
}
operationN() {
return 'Subsystem1: Go!\n';
}
}
class Subsystem2 {
operation1() {
return 'Subsystem2: Get ready!\n';
}
operationZ() {
return 'Subsystem2: Fire!\n';
}
}
class Facade {
constructor(subsystem1, subsystem2) {
this.subsystem1 = subsystem1 || new Subsystem1();
this.subsystem2 = subsystem2 || new Subsystem2();
}
operation() {
let result = 'Facade initializes subsystems:\n';
result += this.subsystem1.operation1();
result += this.subsystem2.operation1();
result += 'Facade orders subsystems to perform the action:\n';
result += this.subsystem1.operationN();
result += this.subsystem2.operationZ();
return result;
}
}
// Usage
const facade = new Facade();
console.log(facade.operation());
Practical Example
Let’s say you’re developing a backend application that involves complex operations like data fetching, processing, and logging. A facade can simplify these operations.
class DataFetcher {
fetchData() {
return 'Data fetched';
}
}
class DataProcessor {
process(data) {
return `${data} processed`;
}
}
class Logger {
log(message) {
console.log(`Log: ${message}`);
}
}
class BackendSystemFacade {
constructor() {
this.fetcher = new DataFetcher();
this.processor = new DataProcessor();
this.logger = new Logger();
}
handleDataOperations() {
const data = this.fetcher.fetchData();
const processedData = this.processor.process(data);
this.logger.log(processedData);
}
}
// Usage
const backendSystem = new BackendSystemFacade();
backendSystem.handleDataOperations();
In this example, BackendSystemFacade
provides a simplified interface to the more complex subsystems (DataFetcher
, DataProcessor
, Logger
). It allows clients to perform complex backend operations in a much simpler way.