Purpose
Facade
(structural pattern) unifies and simplifies access to a complex system or part of it by providing an organized programming interface. This pattern takes inspiration from architecture - the facade, which is the main and often spectacular facade of the building and plays a representative role. This pattern analogically acts as an “overlay” by adding another higher level of abstraction. Therefore, it does not extend the functionality of the system, but makes the use of its functions simpler and the code more readable. Facade
works wherever performing operations in a system entails sequences of operations performed in different parts of the system in a specific order. It is a frequently used pattern and is an inseparable element of many refactoring. A programmer using Facades does not need to know how exactly how given operation works, however it does not release him from reading the attached documentation.
Limitations
Facade
can store references to objects, so there is a strong temptation that unit operations can also be available to the programmer. However this approach, contradicts the idea of this pattern that hides implementation details. When designing facades, it is necessary to analyze which unit operations from its objects should be available in the interface and which ones should be hidden. In such a way that the change in the state of the objects does not affect the proper works of Facade
.
Usage
It can be said that every API or framework is Facade
. It acts as an mediator between a complicated system and a client, providing access to simple but often complex “in the middle” functions. The ‘Facade’ is therefore almost everywhere.
Implementation
Creating Facade
is mainly about aggregating related objects and providing public methods that implement specific execution of the requested operation.
The following listing shows an example of the implementation of Facade
operating on two types of objects, the Utils
and Enum
classes.
Example
The application is a mockup of a music player (Client) who uses own MediaPlayer
(Facade). The programmer creating the player’s applications has to prepare a comprehensible interface that allows another programmer to simply and briefly call up the basic functions of the player such as play
, pause
, stop
, changing songs or adjusting the volume (Facade methods). Knowledge about the way the API is working is not necessary for the programmer to implement the basic functions of the player. In the case of ambiguity or advanced operations, he should refer to the documentation and the source code. Properly programmed MediaPlayer
communicates with various other system elements and external modules, delegates them individual tasks and manages the entire process. Each time, manually creating the basic functions of the player can be time-consuming, unclear and go beyond the possibilities of a novice programmer, so the use of Facade
is highly desirable here. It provides the system functions in a clear way, hiding the mechanism of action. The following listing shows the facade of MediaPlayer
.
‘Facade’ prepared in this way with working modules, allows to easily connect actions to the user interface, which also affects to the readability of the code.
Libraries
The implementation of Facade
is as different as the implementation of a given problem. Therefore there is no single rule for its creation, and there is no reason to exist libraries that streamline the process of implementing Facade
. Each external library (eg: Retrofit
, Glide
) is Facade
in the software being created.