Façade Pattern in TypeScript

This post is 4 years old. (Or older!) Code samples may not work, screenshots may be missing and links could be broken. Although some of the content may be relevant please take it with a pinch of salt.

Design patterns play an important part in software development and they do help us to design better software and write better code.

GoF

Back in 1994, a book was authored by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides that discusses 23 desgin patterns, titled Design Patterns: Elements of Resuable Object-Oriented Software. You may have heard of this book or the authors as Gang of Four (GoF).

The book and the outlined design patterns in them formtulate a solid base for today's software development and those patterns introduced and explained in 1994 are still applicable today and can be used in modern day applications.

Design Pattern types

Design patterns can be categorised into the following categories based on what and how they aim to achieve

  • Creational: deal with object creation
  • Structural: deal with relationships between objects (or other entities)
  • Behavioural: deal with communication patterns between objects
  • Concurrency: deal with multi-threaded paradigms

Façade Pattern

The façade pattern is one of the structural software design patterns. This pattern hides the complexity of subsystems away from the implementor (client) and it provides an easy-to-use interface to the client.

When to use the façade pattern?

The facade pattern is ideal for situations when there are multiple subsystems (multiple APIs) available for the application and we'd like to have a unified interface to get information from those systems and APIs. Think about a real life example, when you apply for a mortgage from a bank. In order for the application to be successful the bank needs to consult a number of systems: fraud systems, credit score systems, other bank's systems so on and so forth. The right implementation would be an interface where someone puts in the applicant's details and presses an 'eligible' button which in turn goes out to all these subsystems and gathers the information.

TypeScript implementation

The adapter pattern could be implemented in any programming language, including vanilla JavaScript as well but I thought it'd be interesting to see how a TypeScript implementation would look like.

It goes without saying that should you want to get the JavaScript implementation, just transpile the TypeScript code to JavaScript, either to ES2015 or to ES5.

Façade example

Let's imagine that we are working on a simple Football Manager type application. In order for players of this application to be able to sign a player to their team, a few checks would have to be in place. In this example we'll make two checks: validate if a particular team has sufficient funds to purchase a player and we also need to make sure that the given player has no active contract. These two checks will come from two, different (imaginary) subsystems.

// subsystem1.ts
export class Contract {
private contractTerminationDateexport class Contract {
private contractTerminationDate: Date;
constructor(terminationDate: Date) {
this.contractTerminationDate = terminationDate;
}
checkActiveContract(date: Date): boolean {
if (date < this.contractTerminationDate) {
return true;
} else {
return false;
}
}
}


// subsystem2.ts
export class TeamFunds {
private totalFunds: number;
constructor(total: number) {
this.totalFunds = total;
}
checkFunds(transferFee: number): boolean {
if (transferFee < this.totalFunds) {
return true;
} else {
return false;
}
}
}

The two classes above are very straight forward - once checks whether a hypothetical player has an active contract, the other one checks if a team has sufficient funds to buy a player.

Now in order to have a simplified interface into these two subsystems, we need to create a façade:

// facade.ts
import { Contract } from './subsystem1';
import { TeamFunds } from './subsystem2';

export class Facade {
private contract: Contract = new Contract(
new Date(new Date().setDate(new Date().getDate() + 10))
);
private funds: TeamFunds = new TeamFunds(200000);

private playerContract: Date;
private playerPrice: number;

constructor(playerPrice: number) {
this.playerContract = new Date();
this.playerPrice = playerPrice;
}

buyPlayer(): void {
if (this.contract.checkActiveContract(this.playerContract)) {
console.log('Player has active contract');
} else {
console.log('Player has no active contract');
if (!this.funds.checkFunds(this.playerPrice)) {
console.log('Player is too expensive to buy.');
} else {
console.log('Player can be bought.');
}
}
}
}

In this file we create a new contract for a player (we set the expiry date of the contract to be today + 10 days). As part of this façade class we also implement the buyPlayer() method which is the only method that we'll need to call when we implement our class. This method uses the conditions specified in the other two subsystems and returns a message.

This is how we'd implement the façade class:

// app.ts
import { Facade } from './facade';

const facade: Facade = new Facade(200001);
facade.buyPlayer();

As you can see the implementation is really straight forward and we don't need to worry about the complexities of the underlying systems.