Facade adds a new layer around a bunch of subsystems, and wraps those. Clients interact with the Facade, and are not aware of the systems.
This article demonstrates Facade pattern implementations in TypeScript. Check the following examples.
Implementation
Follow the steps for the Facade pattern implementation in TypeScript-
- Create a facade class.
- Define private properties of the type of subsystem classes.
- In the constructor initialize the subsystem class.
- Define methods in the facade, and in those methods call methods from the subsystem classes.
- The facade can be initialized and used normally.
Here is a simple Facade implementation-
// Facade pattern implementation in TypeScript
// First subsystem
class Subsystem1 {
operation1(): void {
console.log("Subsystem 1: operation 1");
}
operation2(): void {
console.log("Subsystem 1: operation 2");
}
}
// Second subsystem
class Subsystem2 {
operation3(): void {
console.log("Subsystem 2: operation 3");
}
operation4(): void {
console.log("Subsystem 2: operation 3");
}
}
// Third subsystem
class Subsystem3 {
operation5(): void {
console.log("Subsystem 3: operation 5");
}
}
// Facade
class Facade {
private subsystem1: Subsystem1;
private subsystem2: Subsystem2;
private subsystem3: Subsystem3;
constructor() {
// Initialize subsystems
this.subsystem1 = new Subsystem1();
this.subsystem2 = new Subsystem2();
this.subsystem3 = new Subsystem3();
}
exampleOp1(): void {
// Use operation from subsystem as required
this.subsystem1.operation1();
this.subsystem2.operation3();
}
exampleOp2(): void {
// Use operation from subsystem as required
this.subsystem1.operation2();
this.subsystem3.operation5();
}
}
// Demo
const facade = new Facade();
facade.exampleOp1();
facade.exampleOp2();
Output of the above code will be –
Subsystem 1: operation 1
Subsystem 2: operation 3
Subsystem 1: operation 2
Subsystem 3: operation 5
Examples
Here are a few examples of Facade pattern in TypeScript-
Example #1: Travel Plan
In this example we have some classes which are responsible for handling different part of the travel-
- Car – responsible for operating the car.
- Direction – responsible for giving location/direction related information.
- Toll – handles toll related actions.
- Weather – gives weather information.
We are going to define a facade, and manage all required functionality from the facade.
Car Class [subsystem class]
- Create file “car.ts”.
- Create class “Car”.
// car.ts
class Car {
startEngine(): void {
console.log("Start Engine");
}
stopEngine(): void {
console.log("Stop Engine");
}
goStraight(): void {
console.log("Go Straight: ↑");
}
goLeft(): void {
console.log("Go Left: ←");
}
goRight(): void {
console.log("Go Right: →");
}
getDistanceTravelled(): number {
// This is some random calculation for demo purpose
return ((Math.random() * ((10000 - 100) * 10 + 1)) + 100 * 10) / 10.0;
}
}
export default Car;
Point Class [general class]
Create a class for representing the coordinates of a point. This has props for latitude(lat) and longitude(lng).
// point.ts
class Point {
private lat: number;
private lng: number;
constructor(lat: number, lng: number) {
this.lat = lat;
this.lng = lng;
}
getLat(): number {
return this.lat;
}
getLng(): number {
return this.lng;
}
}
export default Point;
Direction Class [subsystem class]
- Create file “direction.ts”.
- Create class “Direction”.
// direction.ts
import Point from "./point";
class Direction {
private startLat: number;
private startLng: number;
private endLat: number;
private endLng: number;
constructor(startLat: number, startLng: number, endLat: number, endLng: number) {
this.startLat = startLat;
this.startLng = startLng;
this.endLat = endLat;
this.endLng = endLng;
}
public getLocationDetails(lat: number, lng: number) {
console.log("Country: ABC");
console.log("City: DEF");
console.log("State: GHI");
console.log("Zip: 101010");
}
getCurrentLocation(): Point {
// This is some random calculation for demo purpose
const currentLat = (Math.random() * ((90 - (-90) * 10 + 1) - 90 * 10)) / 10.0;
const currentLng = (Math.random() * ((180 - (-180) * 10 + 1) - 180 * 10)) / 10.0;
return new Point(currentLat, currentLng);
}
getNextMove(): string {
// This is some random calculation for demo purpose
const nextMoves = ["straight", "left", "right"];
return nextMoves[Math.floor(Math.random() * nextMoves.length)];
}
getFullRoute(): Point[] {
const points: Point[] = [];
for (let i = 0; i < 10; i++) {
// This is some random calculation for demo purpose
const currentLat = (Math.random() * ((90 - (-90) * 10 + 1) - 90 * 10)) / 10.0;
const currentLng = (Math.random() * ((180 - (-180) * 10 + 1) - 180 * 10)) / 10.0;
points[i] = new Point(currentLat, currentLng);
}
return points;
}
}
export default Direction;
Toll Class [subsystem class]
- Create file “toll.ts”.
- Create class “Toll”.
// toll.ts
import Point from "./point";
class Toll {
getTollPoints(lat: number, lng: number): Point[] {
const points: Point[] = [];
for (let i = 0; i < 10; i++) {
// This is some random calculation for demo purpose
const currentLat = (Math.random() * ((90 - (-90) * 10 + 1) - 90 * 10)) / 10.0;
const currentLng = (Math.random() * ((180 - (-180) * 10 + 1) - 180 * 10)) / 10.0;
points[i] = new Point(currentLat, currentLng);
}
return points;
}
getTollAmount(tollPointId: number): number {
// This is some random calculation for demo purpose
return (Math.random() * (((100 - 1) * 10 + 1)) + 10) / 10.0;
}
getTotalToll(lat: number, lng: number): number {
// This is some random calculation for demo purpose
return (Math.random() * (((100 - 1) * 10 + 1)) + 10) / 10.0;
}
}
export default Toll;
Weather Class [subsystem class]
- Create file “weather.ts”.
- Create class “Weather”.
// weather.ts
class Weather {
getWeatherInfo(lat: number, lng: number): void {
console.log("Temperature: 20.7");
console.log("Precipitation: 1%");
console.log("Humidity: 73%");
console.log("Wind: 8 km/h");
}
}
export default Weather;
Facade Class
This travel facade contains the functionality required by the client.
- Create file “travel-facade.ts”.
- Create class “TravelFacade”.
- Define private properties for objects of type “Car”, “Toll”, “Weather”, and “Direction”.
- In the constructor initialize the objects.
- Declare methods as per requirement of the client, and in the method implementations use/call the methods from the subsystem(Car, Weather, Toll, Direction) classes.
// travel-facade.ts
import Car from "./car";
import Direction from "./direction";
import Point from "./point";
import Toll from "./toll";
import Weather from "./weather";
class TravelFacade {
private startLat: number;
private startLng: number;
private endLat: number;
private endLng: number;
private direction: Direction;
private toll: Toll;
private car: Car;
private weather: Weather;
// define constructor
constructor(startLat: number, startLng: number, endLat: number, endLng: number) {
this.startLat = startLat;
this.startLng = startLng;
this.endLat = endLat;
this.endLng = endLng;
// Initialize classes
this.direction = new Direction(startLat, startLng, endLat, endLng);
this.car = new Car();
this.toll = new Toll();
this.weather = new Weather();
}
getRoute(): Point[] {
return this.direction.getFullRoute();
}
getLocationInfo(lat: number, lng: number) {
this.direction.getLocationDetails(lat, lng);
this.weather.getWeatherInfo(lat, lng);
}
getCurrentLocation(): Point {
return this.direction.getCurrentLocation();
}
operateCar(): void {
const fullRoute = this.direction.getFullRoute();
this.car.startEngine();
for (let point of fullRoute) {
const nextMove = this.direction.getNextMove();
switch (nextMove) {
case "straight": this.car.goStraight(); break;
case "left": this.car.goLeft(); break;
case "right": this.car.goRight(); break;
}
}
this.car.stopEngine();
}
getTotalTollAmount(lat: number, lng: number) {
console.log("Total Toll Amount: " + this.toll.getTotalToll(lat, lng));
}
}
export default TravelFacade;
Demo
We can not initialize the facade and use the methods from that.
// demo.ts
import TravelFacade from "./travel-facade";
const travelFacade = new TravelFacade(10, 10, 20, 30);
const currentLocation = travelFacade.getCurrentLocation();
console.log("Current Latitude: " + currentLocation.getLat());
console.log("Current Longitude: " + currentLocation.getLng());
travelFacade.getLocationInfo(20, 30);
travelFacade.getTotalTollAmount(20, 30);
travelFacade.operateCar();
Output
Current Latitude: 3.360968867455751
Current Longitude: 15.476935275479192
Country: ABC
City: DEF
State: GHI
Zip: 101010
Temperature: 20.7
Precipitation: 1%
Humidity: 73%
Wind: 8 km/h
Total Toll Amount: 6.488174883078076
Start Engine
Go Straight: ↑
Go Right: →
Go Straight: ↑
Go Right: →
Go Right: →
Go Right: →
Go Straight: ↑
Go Right: →
Go Straight: ↑
Go Left: ←
Stop Engine
Source Code
Use the following link to get the source code:
Example | Source Code Link |
---|---|
Example #1: Travel Plan | GitHub |
Other Code Implementations
Use the following links to check Facade pattern implementation in other programming languages.