The code is available on GitHub here
The Facade Pattern is responsible to make a complex subsystem that consists of different components, into a simpler one, providing a simple interface. However, Facade still leaves the subsystem accessible so it can be used directly. The interface defined by the Facade is a higher level, that makes the subsystem easier to use.
When to use
Use the Facade Pattern for a process which is carried on by many different components that need to be executed in a certain order.
Hiding the overhead of calling different components in order to complete a certain operation makes the use of the software much easier.
Use the Facade Pattern in case you want to make a system that is much easier to be integrated and reused.
Instead of having the user figure out what components needs to be called in order to make single operation, you can expose a simple facade that handles the complexity and provides a straightforward interface. This approach is very powerful in all sorts of libraries that want to provide a simpler interface for its users.
Finally, the Facade Pattern satisfies the Least Knowledge principle (or the Law of Demeter ):
An object should never know the internal details of other objects
This principle is a guideline to reduce the interactions between objects to the following:
- To the object itself. You can use every instance variable inside of an object.
- Objects passed as parameters to a method. Inside this method you can use those parameters but only those. You shouldn’t call methods of those objects in order to obtain other objects.
- Any object that is created inside a method can be freely used.
Finally, the Least Knowledge principle has the following advantages:
- It makes the design less coupled. That means, whenever any subsystem used by the Facade is changed, the user of the Facade doesn’t need to be changed.
- The system is less fragile. When you build a lot more dependencies than is needed then your system tends to be more unstable and harder to maintain.
How to implement
The implementation of the Facade Pattern is very simple. We need to bring the different components of the subsystem together into a unified interface. Additionally, the facade interface will expose methods in order to execute specific operations using the referenced components.
Any client will have a reference to the Facade and the Facade class will have all the necessary references to the components as shown in the class diagram below.
Example – Coffee machine Facade
Now that we have a good grasp of the Facade Pattern, we will implement a coffee machine that utilizes a facade in order to provide a simple and clean interface for its users.
This interface will be responsible to hide the complexity of making a coffee. This process involves controlling various subsystems of the coffee machine that the client shouldn’t be aware of.
The various subsystems
Before we dive into details of the Facade class, we have to build the various subsystems for a coffee machine.
Grinder
Suppose we have already fill the coffee machine with grains of coffee and the machine is equipped with a component that grinds a correct dose.
public class Grinder
{
public enum Size
{
ExtraCoarseGrind,
CoarseGrind,
MediumCoarseGrind,
MediumGrind,
MediumFineGrind,
FineGrind,
ExtraFineGrind
}
private Size _size;
public Grinder()
{
_size = Size.FineGrind;
}
public void SetGrindSize(Size size)
{
_size = size;
}
public void Grind()
{
Console.WriteLine("Grinding Coffee at size: " + _size);
// grind
Console.WriteLine("Grinding done");
}
}
Heater
The Heater is responsible to keep the water warm in a certain temperature. Its implementation is shown below.
public class Heater
{
public void On()
{
Console.WriteLine("Turning the heater on");
}
public void Off()
{
Console.WriteLine("Turning the heater off");
}
public void SetTemperature(int degrees)
{
Console.WriteLine($"Heating the water at {degrees} degrees");
}
}
Pump
The Pump is used to move the water through the grained coffee in order to end up in a cup of coffee.
public class Pump
{
public void PumpWater()
{
Console.WriteLine("Pumping the water..");
// pumping
Console.WriteLine("Pumping the water done");
}
}
The CoffeeMachineFacade
Let’s step through the construction of the CoffeeMachineFacade class. It will have a single method, makeCoffee and a reference to all the subsystems that we previously developed.
The CoffeeMachineFacade class responsibility is to coordinate all subsystems in order to make a coffee.
public class CoffeeMachineFacade
{
Pump pump;
Heater heater;
Grinder grinder;
public CoffeeMachineFacade(Pump pump, Heater heater, Grinder grinder)
{
this.pump = pump;
this.heater = heater;
this.grinder = grinder;
}
public void MakeEspresso()
{
heater.On();
heater.SetTemperature(92); // prepare the right temperature
grinder.Grind();
pump.PumpWater();
heater.Off();
}
}
Usage
Lastly, we instantiate a CoffeeMachineFacade in order to use its makeCoffee method. Normally the client gets the Facade instance from its constructor.
public static void Main()
{
CoffeeMachineFacade facade = new CoffeeMachineFacade(new Pump(), new Heater(), new Grinder());
facade.MakeEspresso();
Console.WriteLine("Coffee is ready!");
}
The result of the previous code is shown below.
Turning the heater on
Heating the water at 92 degrees
Grinding Coffee at size: FineGrind
Grinding done
Pumping the water..
Pumping the water done
Turning the heater off
Coffee is ready!
All the heavy work is done by the CoffeeMachineFacade. Any client that uses the facade is unaware of how a coffee is made, which makes our design more stable.
Recommendations
If you want to learn more, refresh or better understand design patterns and software design in general, I also recommend reading the following books:
A must in Design Patterns
A very well written book with plenty of examples and insights