Facade

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

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.

javascript
	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.