JS and Design Patterns - Final Chapter π
devlazar
Posted on January 27, 2021
Table Of Contents
* π€INTRODUCTION
* π¨ABOUT FACADE PATTERN
* πVISUAL REPRESENTATION
* πCALL OPERATOR EXAMPLE
* πMORTGAGE EXAMPLE
* π€IRON MAN EXAMPLE
* βAPPLICABILITY
* β
PROS
* βCONS
# π₯CHALLENGES
* πTHANK YOU
π€ INTRODUCTION
WELCOME, my dear coders, to the FINAL CHAPTER of the JavaScript and Design Patterns series. I hope you are all having a great day. I would like to say that I really had fun writing these articles, and I am so glad that these articles helped or may help you in the future. In the previous chapters, we went through the different concepts and different categories of the JavaScript and Design Patterns paradigm. We talked about the Singleton Pattern, the Decorator Pattern, the Observer Pattern, etc. And it is all available to you right here on Dev.to;
Also, I would like to mention that I am available for collaboration, mentoring, talking, and having fun. You can connect with me via Twitter, LinkedIn, Ko-fi or via Email. Please do not hesitate to contact me if you have some ambiguities or just want to say hey.
In this last chapter, we are talking about the Facade Design Pattern.
π¨ ABOUT FACADE
The Facade Design Pattern is a structural design pattern that provides a simplified interface to a library, a framework, or any other complex set of classes. A facade can:
- Make a software library easier to use, understand and test, since the facade has convenient methods for common tasks;
- Make the library more readable, for the same reason;
- Reduce dependencies of outside code on the inner workings of a library, since most code uses the facade, thus allowing more flexibility in developing the system In other words, the Facade Design Pattern provides a unique interface to a whole subsystem. The Facade Design Pattern defines an interface on a higher level, which makes usage of the subsystem much easier.
π VISUAL
π CALL OPERATOR EXAMPLE
When you call a shop to place a phone order, an operator is your facade to all services and departments of the shop. The operator provides you with a simple voice interface to the ordering system, payment gateways, and various delivery services.
π MORTGAGE EXAMPLE
This example shows the usage of the Facade Design Pattern like an object of the class MortgageApplication - that provides a simplified interface towards the set of classes that have a role to determine client's creditability.
Let's see a very simple code implementation of the mortgage example π (β As always, read the comments)
//Subsystem ClassA
class Bank{
//A function that simulates determining if the user
//has sufficient savings
hasSufficientSavings(customer, amount){
console.log(`Check bank for ${customer.getName()}...`);
return amount > 100000;
}
}
//Subsystem ClassB
class Credit{
//check if the user has a good credit
hasGoodCredit(customer){
console.log(`Check credit for ${customer.getName()}...`);
return true;
}
}
//Subsystem ClassC
class Loan{
//check if the user has no bad loans
//you can make this function do whatever you want
//in order to determine if the user has a bad loan
hasNoBadLoans(customer){
console.log(`Check loans for ${customer.getName()}...`)
return true;
}
}
//Simple Customer class
class Customer{
constructor(name){
this.name = name;
}
getName() { return this.name; }
}
//Facade
class Mortgage{
//When creating mortgage we are also creating
//instance of the class Bank, instance of the class Loan and an instance of the class Credit
constructor(){
this.bank = new Bank();
this.loan = new Loan();
this.credit = new Credit();
}
//a function that checks if the customer is eligible
isEligible(customer, amount){
console.log(`${customer.getName()} applies for $${amount} loan`);
var eligible = true;
//check creditability
if (!this.bank.hasSufficientSavings(customer, amount)){
eligible = false;
}else if (!this.loan.hasNoBadLoans(customer)){
eligible = false;
}else if (!this.credit.hasGoodCredit(customer)){
eligible = false;
}
return eligible;
}
}
//creating mortgage
var mortgage = new Mortgage();
var customer = new Customer("Ann McKinsey");
var eligable = mortgage.isEligible(customer, 125000);
console.log("%c%s",
"color: white; background: lightgreen; font-size: 24px; border: 1px solid red; border-radius: 5px; padding: 5px;",
`π€ Customer: ${ customer.getName() } has been ${eligable ? 'Approved':'Rejected'}`);
π€ IRON MAN EXAMPLE
Iron Man, my favorite superhero. The complexity of the suit design and optimization perfectly matches the complexity of the creator's mind (Tony Stark). Iron Man's "butler", Jarvis, is the facade to the entire system that Tony Stark, a.k.a. Iron Man, is using when communicating with the suit of armor. Let's describe that communication with the Facade Design Pattern, let's write the code for that! π
//Subsystem 1
class Suit{
constructor(name){
this.name = name;
}
getName() { return this.name; }
}
//Subsystem 1
class Core{
constructor(name){
this.name = name;
}
getCore() { return this.name; }
}
//Subsystem 3
class ElectricalSystems{
checkIfElectircalSystemOk(suit){
console.log(`Checking if electrical systems are ok on the ${suit.getName()} suit of armor`);
return true;
}
}
//Subsystem 4
class MechanicalSystem{
checkIfMechanicalSystemOk(suit){
console.log(`Checking if mechanical systems are ok on the ${suit.getName()} suit of armor`);
return true;
}
}
//Subsystem 5
class DecompressionSystem{
checkIfDecompressionSystemOk(suit){
console.log(`Checking if decompression systems are ok on the ${suit.getName()} suit of armor`);
return true;
}
}
//Subsystem 6
class CommunicationSystem{
checkIfCommunicationSystemOk(suit){
console.log(`Checking if communication systems are ok on the ${suit.getName()} suit of armor`);
return true;
}
}
//Subsystem 7
class FlyingSystem{
checkIfFlyingSystemOk(suit){
console.log(`Checking if flying systems are ok on the ${suit.getName()} suit of armor`);
return true;
}
}
//Subsystem 8
class VisualSystem{
checkIfVisualSystemOk(suit){
console.log(`Checking if visual systems are ok on the ${suit.getName()} suit of armor`);
return true;
}
}
//Subsystem 9
class AutocalibrationSystem{
checkIfAutocalibrationSystemOk(suit){
console.log(`Checking if autocalibration systems are ok on the ${suit.getName()} suit of armor`);
return true;
}
}
class SuperHero{
constructor(){}
//...
}
class TonyStark extends SuperHero{
constructor(){
super();
this.name = "Tony Stark";
this.description = "Billionaire, Playboy, Philanthropist";
}
getTony() { return this.name; }
}
//Facade
class Jarvis{
constructor(){
this.suit = new Suit("MARK 85");
this.core = new Core("CORE ZZ-112F");
this.electricalSystem = new ElectricalSystems();
this.mechanicalSystem = new MechanicalSystem();
this.decompressionSystem = new DecompressionSystem();
this.communicationSystem = new CommunicationSystem();
this.flyingSystem = new FlyingSystem();
this.visualSystem = new VisualSystem();
this.autocalibrationSystem = new AutocalibrationSystem();
}
checkSystems(tony){
console.log(`${tony.getTony()}: Jarvis?`);
console.log(`Jarvis: Good morning, sir.`);
console.log(`${tony.getTony()}: Check the systems. π`);
console.log(`Jarvis: Right away, sir.`);
console.log(`Initializing core ${this.core.getCore()}...`);
var systemsOk = true;
if (!this.electricalSystem.checkIfElectircalSystemOk(this.suit)){
systemsOk = false;
}else if (!this.mechanicalSystem.checkIfMechanicalSystemOk(this.suit)){
systemsOk = false;
}else if (!this.decompressionSystem.checkIfDecompressionSystemOk(this.suit)){
systemsOk = false;
}else if (!this.communicationSystem.checkIfCommunicationSystemOk(this.suit)){
systemsOk = false;
}else if (!this.flyingSystem.checkIfFlyingSystemOk(this.suit)){
systemsOk = false;
}else if (!this.visualSystem.checkIfVisualSystemOk(this.suit)){
systemsOk = false;
}else if (!this.autocalibrationSystem.checkIfAutocalibrationSystemOk(this.suit)){
systemsOk = false;
}
return systemsOk;
}
}
//initialize jarvi
var jarvis = new Jarvis();
var tony = new TonyStark();
var systemStatus = jarvis.checkSystems(tony);
if (!systemStatus){
console.log("%c%s",
"color: black; background: red; font-size: 24px; border: 1px solid red; border-radius: 5px; padding: 5px;",
`Jarvis: Sir, we have a problem with this suit of armor.`);
}else{
console.log("%c%s",
"color: black; background: lightgreen; font-size: 24px; border: 1px solid red; border-radius: 5px; padding: 5px;",
`Jarvis: All systems are fine. We are ready, sir!`);
}
β APPLICABILITY
You can use the Facade pattern when you need to have a limited but straightforward interface to a complex subsystem. Often, subsystems get more complex over time. Even applying design patterns typically leads to creating more classes. A subsystem may become more flexible and easier to reuse in various contexts, but the amount of configuration and boilerplate code it demands from a client grows even larger. The Facade Design Pattern attempts to fix this problem by providing a shortcut to the most used features of the subsystem which fit most client requirements.
You can also use the Facade pattern when you want to structure a subsystem into layers.
β PROS
- Code isolation from the complexity of a subsystem
β CONS
- A facade can become a God object coupled to all classes of an application.
π₯ CHALLENGES
- Subsystems are connected with the facade layer. So, you need to take care of an additional layer of coding.
- When the internal structure of a subsystem changes, you need to incorporate the changes in the facade layer also.
π THANK YOU FOR READING!
References:
School notes...
refactoring
Please leave the comment, tell me about you, about your work, comment your thoughts, connect with me!
β SUPPORT ME AND KEEP ME FOCUSED!
Have a nice time hacking! π
Posted on January 27, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.