Description
The facade design pattern provides an interface that offers a simplified way to access a complex subsystem. In other words, it allows certain functionalities of a complicated system to be made simple by exposing certain functionalities.
Scenario
🖥️ How does a computer work? As you know, it is a complex system of elements interacting together:
- 🧠 The CPU: It is the brain of our computer.
- 💾 Hard drives: They allow us to store information in our computer.
- 📝 RAM: Allows us to temporarily store data for faster execution.
All of these elements make up a computer. In our case, we can say that this computer is our facade that will expose certain functionalities outside of all the complexity of the elements. Our subsystem will then represent our different computer elements exposed above.
Pros and Cons
Pros | Cons |
---|---|
✔️Reduces complexity | ❌Code complexity in the case where we create a lot of subsystems. |
✔️Isolation of subclasses | ❌Dependency of subclasses to the interface, which creates coupling. |
✔️Flexibility |
When to use it?
💡 You have a complex subsystem that you want to expose simply to the client. 💡 You want to structure a subsystem on several layers.
UML Diagram
In this example, we are developing a computer that will display messages from its subsystems. So far, the system is simple, but as you know, a computer can quickly become complex!
Faced with this situation, we notice that a facade pattern is a very good solution.
Suppose we decide to add all the components of a computer and detail their functions? In our case, our system becomes complex! Complex, okay, but we only want to expose certain simple functionalities of our system to have easy interactivity for the user. This is why the creation of our facade will represent our computer. Thus, we can easily add or remove elements from our subsystem in this interface without linking the components to each other.
Implementation
Before creating our facade, we need to create the components of our subsystem: CPU, Memory, HardDrive. Here, we will display simple messages characterizing the different elements.
CPU
package com.design.facade.subsystem;
public class CPU {
public void freeze() {
System.out.println("Computer freezing ... ");
}
public void jump(long position) {
System.out.println("Jumping to..." + position);
}
public void execute() {
System.out.println("Computer executing commands...");
}
}
HardDrive
package com.design.facade.subsystem;
public class HardDrive {
public byte[] read(long Iba, int size) {
return new byte[] {'f', 'z'};
}
}
Memory
package com.design.facade.subsystem;
public class Memory {
public void load(long position, byte[] data) {
System.out.println("Added item to memory.. " + position);
}
}
Great! So our computer components are implemented and we have assigned behaviors to each of them. To create our facade, we will link these elements to make them easily available under a common interface.
BookDecorator
package com.design.facade.facade;
import com.design.facade.subsystem.CPU;
import com.design.facade.subsystem.HardDrive;
import com.design.facade.subsystem.Memory;
public class ComputerFacade {
private CPU processor;
private Memory ram;
private HardDrive hardDrive;
public ComputerFacade(CPU processor, Memory ram, HardDrive hardDrive) {
this.processor = processor;
this.ram = ram;
this.hardDrive = hardDrive;
}
public void start() {
processor.freeze();
ram.load(132, hardDrive.read(3456, 89));
processor.jump(132);
processor.execute();
}
}
We have now created our facade, which has allowed us to simplify the interactions of our system with a single method. Just like in real life, we press a button and everything runs smoothly. Our contract is fulfilled, we have provided a simplified subsystem to the client!
Now we have everything we need to test our code in our main class! We just need to implement it:
Main
package com.design.facade;
import com.design.facade.facade.ComputerFacade;
import com.design.facade.subsystem.CPU;
import com.design.facade.subsystem.HardDrive;
import com.design.facade.subsystem.Memory;
public class Main {
public static void main(String[] args) {
ComputerFacade facade = new ComputerFacade(new CPU(), new Memory(), new HardDrive());
facade.start();
}
}
Result:
Computer freezing ...
Added item to memory.. 132
Jumping to...132
Computer executing commands...
Here, we have finished our implementation. What we can notice is:
- We have exposed functionalities in a facade in a simple way.
- Our system can be easily extended.
- We can add functionalities without impacting the others.