Groups of related subsystems in an application can make for complex looking code when an action requires a lot of repetitive calls to the various systems. For some, the natural thing to do is encapsulate those large chunks of repetitive code into container classes and methods, masking the complex code behind a single function call. Many developers might not realize when they do it, but they're actually implementing a Facade Pattern.
Assumptions
- Basic programming knowledge
- Knowledge of basic <a href="https://www.devmaking.com/learn/design-patterns/design-pattern-modeling/" target="_blank" style="color:inherit;">Modeling Notation</a>
What is the Facade Pattern?
A facade in software development is a structural design pattern intended to mask complex, interdependent code by wrapping it into a single function.
<div style="width:100%; margin:auto;text-align:center;"><img src="https://www.devmaking.com/img/topics/designpatterns/FacadePattern_01.png" alt="facade pattern UML" style="max-width:95%;"> </div>
For example, its much easier for a developer to type a single line of code to do something as opposed to writing many lines of code such as this:
cpu.startup();
memory.flush();
memory.start();
graphics.initialize();
pageFile.load();
// and so on...
The idea of a facade would be to encapsulate all this code into a single class that would allow us to do something like this:
// Executes all the code above:
computer.startup();
Conceptualization
To further grasp the idea, let's say we're creating a free-for-all game where players can run around and collect loot. We're going to have a lot of interdependent classes that need to be executed when initializing the match, which is where the facade will come in to make it look nice and neat to a client.
Constructing the Classes
First, let's say we have the following set of classes implemented already. Note that their structure doesn't have any bearing on the actual facade pattern; they're just here for example purposes to demonstrate a collection of related classes:
// Conceptual classes:
class GameMap {
void loadTextures() {
print("Loaded textures");
}
void loadSpawnPoints() {
print("Loaded spawn points");
}
}
class LootSystem {
String tableID;
boolean tableLoaded;
void setLootTable(String tableID) {
this.tableID = tableID;
print("Set the loot table to " + tableID);
}
void loadLootTable() {
if (tableID is not null) {
tableLoaded = true;
print("Loot table is loaded");
}
else {
throw Exception("No loot table set!");
}
}
}
class UIController {
void initializeUI() {
print("UI initialized");
}
void setInteractable(boolean state) {
print("UI interaction set to " + state);
}
}
class InventorySystem {
void load() {
print("Inventory loaded");
}
void save() {
print("Inventory saved");
}
}
If we were to implement this code in our client application as is, starting up a match would create a lot of bulky code like this:
static void main(String[] args) {
// Initializing our subsystems:
GameMap map = new GameMap();
LootSystem loot = new LootSystem();
UIController uiController = new UIController();
InventorySystem inventory = new InventorySystem();
// Starting up a game match:
inventory.load();
loot.setLootTable("Normal Loot");
loot.loadLootTable();
map.loadTextures();
map.loadSpawnPoints();
uiController.initializeUI();
uiController.setInteractable(true);
// later on when we want to end a match...
inventory.save();
uiController.setInteractable(false);
}
While this gets the job done, it sure is a lot of code to have laying around, especially given that it is code which might pop up again later on! To amend this, we're going to create a facade to wrap this.
Creating the Facade
A facade can be a concrete class or an implementation of a facade interface. For simplicity, this example uses a concrete class for the facade. When creating the facade, we'll store references to all of the interdependent classes, and in our facade method(s), will copy the bulky code into them:
class GameManagerFacade {
GameMap map = new GameMap();
LootSystem loot = new LootSystem();
UIController uiController = new UIController();
InventorySystem inventory = new InventorySystem();
void initializeMatch() {
inventory.load();
loot.setLootTable("Normal Loot");
loot.loadLootTable();
map.loadTextures();
map.loadSpawnPoints();
uiController.initializeUI();
uiController.setInteractable(true);
}
void endMatch() {
inventory.save();
uiController.setInteractable(false);
}
// ...
}
With the facade, now our client code will look much simpler and will be easy to reason about!
static void main(String[] args) {
GameManagerFacade gameManager = new GameManager();
gameManager.initializeMatch();
//...
gameManager.endMatch();
}
> If we wanted to implement different game modes, it would be a good idea to create an interface for the facade!
Recommended Resources
- <a target="_blank" href="https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=devmaking-20&linkId=bc32087110669f75d93b216df79816f0" style="color:#fff;border-radius:3px;background-color:#888;padding:1px 5px">Head First Design Patterns: A Brain-Friendly Guide</a> : An excellent primer for learning design patterns in a pragmatic way.
- <a target="_blank" href="https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=devmaking-20&linkId=ae25d94c4ea49870eb3115e0e4d2de90" style="color:#fff;border-radius:3px;background-color:#888;padding:1px 5px">Design Patterns: Elements of Reusable Object-Oriented Software</a> : The reference guide made famous by Gang of Four, still widely used today.
- <a href="https://www.draw.io" target="_blank" style="color:#fff;border-radius:3px;background-color:#888;padding:1px 5px">Draw.io</a>: A free, open-source tool for designing diagrams with built-in support for UML diagrams to make your own!