Facade Design Pattern
Structural: Facade Pattern
What is the facade design pattern in JavaScript?
View Answer:
class ComplexSystem {
operationA() {
return 'Doing complex operation A\n';
}
operationB() {
return 'Doing complex operation B\n';
}
operationC() {
return 'Doing complex operation C\n';
}
}
class Facade {
constructor(system) {
this.system = system;
}
simpleOperation() {
let result = '';
result += this.system.operationA();
result += this.system.operationB();
result += this.system.operationC();
return result;
}
}
// Using the facade
let system = new ComplexSystem();
let facade = new Facade(system);
console.log(facade.simpleOperation()); // Runs all operations at once and masks the complexity.
In this example, ComplexSystem
has multiple methods (operationA
, operationB
, and operationC
) that can be called individually, but it may be more convenient to perform these operations all at once. The Facade
class provides a method simpleOperation
that does exactly that.
When a client interacts with the Facade
instance (by calling simpleOperation
), the facade forwards those requests to appropriate methods of the ComplexSystem
. The client doesn't need to be aware of the ComplexSystem
class, which encapsulates complex functionality. This simplifies the client's interaction with the system.
The Facade pattern belongs to which pattern family?
View Answer:
Why use the Facade Design Pattern?
View Answer:
It gets used in communicating with methods in a library without understanding what is happening behind the scenes. JavaScript libraries, such as jQuery, are an example.
What are the Façade Pattern's object participants?
View Answer:
- Facade – The Façade understands which sub-systems are in charge of a request and routes client requests to the appropriate sub-system objects.
- Sub Systems – A sub-system implements and executes specialized sub-system activities, but it has no cohesive knowledge or connection to the Façade itself.
// Subsystem classes
class SubSystemOne {
methodOne() {
console.log('SubSystemOne Method');
}
}
class SubSystemTwo {
methodTwo() {
console.log('SubSystemTwo Method');
}
}
class SubSystemThree {
methodThree() {
console.log('SubSystemThree Method');
}
}
// Facade
class Facade {
constructor() {
this.one = new SubSystemOne();
this.two = new SubSystemTwo();
this.three = new SubSystemThree();
}
wrapOperation() {
console.log('Wrap Operation Starts');
this.one.methodOne();
this.two.methodTwo();
this.three.methodThree();
console.log('Wrap Operation Ends\n');
}
}
// Client code
const facade = new Facade();
facade.wrapOperation();
// This will output:
// Wrap Operation Starts
// SubSystemOne Method
// SubSystemTwo Method
// SubSystemThree Method
// Wrap Operation Ends
In this example, Facade
is the facade, SubSystemOne
, SubSystemTwo
, and SubSystemThree
are the subsystem classes. wrapOperation
in Facade
provides a simplified interface for the operations in the subsystems, and is the method that the client will call.
The subsystem classes may be complex and difficult to use directly, so the facade provides a simple interface to the complex subsystems. The subsystem classes handle tasks required by the facade, but the facade encapsulates this complexity and exposes a simplified interface to the clients. The clients only interact with the facade, not the subsystems.
What are some of the benefits of using the Facade pattern?
View Answer:
What are some of the disadvantages of employing the Facade pattern?
View Answer:
Are there any alternatives to using the facade pattern?
View Answer:
How does the Facade Pattern improve code readability?
View Answer:
How does the Facade Pattern affect coupling?
View Answer:
Can the Facade Pattern increase performance?
View Answer:
Can multiple facades exist for a subsystem?
View Answer:
// Subsystem classes
class SubSystem {
methodA() {
console.log('SubSystem Method A');
}
methodB() {
console.log('SubSystem Method B');
}
methodC() {
console.log('SubSystem Method C');
}
}
// First Facade
class Facade1 {
constructor(system) {
this.system = system;
}
operationX() {
console.log('Operation X Starts');
this.system.methodA();
this.system.methodB();
console.log('Operation X Ends\n');
}
}
// Second Facade
class Facade2 {
constructor(system) {
this.system = system;
}
operationY() {
console.log('Operation Y Starts');
this.system.methodB();
this.system.methodC();
console.log('Operation Y Ends\n');
}
}
// Client code
let system = new SubSystem();
let facade1 = new Facade1(system);
facade1.operationX();
let facade2 = new Facade2(system);
facade2.operationY();
// This will output:
// Operation X Starts
// SubSystem Method A
// SubSystem Method B
// Operation X Ends
// Operation Y Starts
// SubSystem Method B
// SubSystem Method C
// Operation Y Ends
In this example, the SubSystem
has three methods, and two different facades (Facade1
and Facade2
) provide different simplified interfaces to these methods. Facade1
provides operationX
, which uses methodA
and methodB
of the SubSystem
, and Facade2
provides operationY
, which uses methodB
and methodC
.
The client code decides which facade to use based on the operations it wants to perform. The use of multiple facades allows different clients or different parts of the code to interact with the subsystem in different ways, while still abstracting the complexity of the subsystem.