Facade Design Pattern

Classic GOF Structural Design Patterns

 
  

Intent

The Facade Pattern is used to encapsulate or hide a complex subsystem behind a simple interface. It hides much of the complexity and makes the subsystem easy to use. A facade allows us to make changes to a complex subsystem and not affect any of the clients.

It is used when:

  • A simple interface is needed to provide access to a complex system.
  • There are many dependencies between system implementations and clients
  • Systems and subsystems should be layered.
facade patterns
  

Problem

The Facade pattern should be used when you have a complex system or set of subsystems and want to provide a simplified interface to a client. This is especially important when the details of the "hidden" systems change frequently.

  

Discussion

The whole purpose of implementing a Facade is to simplify access to or hide the complexity of a complex system. Why would we want to do this? First of all, it reduces the learning curve dramatically for users accessing that system. Additionally, it serves to decouple the actual system details away from the clients so that it can be changed without effecting them.

A perfect real world example of a facade is a blanket on a bed. Underneath the blanket, the sheets could be pulled tight or a rumpled mess. The blanket acts as a facade and hides the underlying details of how the bed is made. To any casual observer, the blanket is the only thing they will see and, in effect, "becomes" the bed as far as they are concerned.

In practice, the Facade should merely be a simple facilitator. If you start moving down the path where the facade is an all-knowing powerful object, you are using the facade pattern incorrectly.

  

Structure

There is not really much to the structure of a Facade design pattern. It consists of a single object that does two basic things (and shouldn't do much more):

  • knows how to call and use objects in the subsystem that it is encapsulating, and
  • can present a much simplified interface to any consumers of the facade

This allows the details and complexity of the subsystem to be completely hidden from consumers. It also allows for radical alterations of the implementation of the system, up to and including wholesale replacement.


facade pattern structure

As you can see in the diagram above, the the structure is fairly basic:

  • Facade - knows which subsystem classes are responsible for a request and delegates client requests to appropriate subsystem objects.
  • Subsystem classes - the actual workhorse - receives and processes requests from the facade object, have no knowledge of the outside world.
  

Practical Example

For a practical example of the Facade Pattern in a real world usage scenario, lets imagine that we have a complex mortgage approval system. We certainly wouldn't want anyone directly interfacing with all the functions in the system, instead, we want to provide a simplified interface that allows consumers to get approval on a new mortgage. We want something simple and easy to consume and we want to "hide" or encapsulate the complex mortgage system.


gof facade example

Much like the generic diagram in STRUCTURE above, the Mortgage Facade will act as the interface for the entire mortgage subsystem. It will provide a minimal surface area and it needs to be easy to consume. In this case, the Mortgage Facade will sit in front of a number of the subsystem's components - specifically, the bank, customer, credit, and loan systems.

Let's solve this sample with some practical code below.

  

Code Samples

Below, you will find examples of the Facade implemented in four different commonly used languages. Each one of the examples implements the exact same scenario as described in the PRACTICAL EXAMPLE section above.

Each sample will use a Facade to allow for easily accessing and encapsulating the mortgage system to approve a mortgage..


C# Facade Code Sample

In this C# example, the Facade pattern is used


Java Facade Code Sample

In this Java example, the Facade pattern is used.


Typescript Facade Code Sample

In this TypeScript example, the Facade pattern is used


JavaScript Facade Code Sample

In this JavaScript example, the Facade pattern is used.


  

Considerations

  1. Identify a simpler, unified interface for the subsystem or component.
  2. Design a 'wrapper' class that encapsulates the subsystem.
  3. The facade/wrapper captures the complexity and collaborations of the component, and delegates to the appropriate methods.
  4. The client uses (is coupled to) the Facade only.
  5. Consider whether additional Facades would add value.
  

Additional Notes

  • Facade defines a new interface, whereas Adapter uses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.
  • Whereas Flyweight shows how to make lots of little objects, Facade shows how to make a single object represent an entire subsystem.
  • Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communications between colleague objects. It routinely "adds value", and it is known/referenced by the colleague objects. In contrast, Facade defines a simpler interface to a subsystem, it doesn't add new functionality, and it is not known by the subsystem classes.
  • Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.
  • Facade objects are often Singletons because only one Facade object is required.
  • Adapter and Facade are both wrappers; but they are different kinds of wrappers. The intent of Facade is to produce a simpler interface, and the intent of Adapter is to design to an existing interface. While Facade routinely wraps multiple objects and Adapter wraps a single object; Facade could front-end a single complex object and Adapter could wrap several legacy objects.
  • By introducing the Facade into your code, you will be hard-wiring subsystems into the Facade. This is fine if the subsystem never changes, but if it does, your Facade could be broken. Therefore, developers working on the subsystem should be made aware of any Facade around their code.
  • Sometimes the pattern can be overused in simple scenarios, which will lead to redundant implementations.