Facade is a structural design pattern that let you provide a simplified interface to a complex system of classes, library or framework.
Imagine the code that has to work with a large set of objects of some complex library or framework. You have to manually initialize all these objects, keep track of the dependencies, correct order and so on.
In the end, the business logic of your classes becomes tightly coupled to the implementation details of third party library. Such code is pretty hard to comprehend and maintain.
The facade is a class that provides a simple interface to a complex subsystem containing dozens of classes. The facade may have limited functionality in comparison to working with subsystem directly. However, it includes only those features that clients really care about.
Facade is handy when you use a sophisticated library with a lot of moving parts, but you need only a fraction of its functionality.
For instance, an app that uploads short videos with cats to the Youtube could use a professional video conversion library. But all that it really needs is a class with a single method
encode(filename, format). After creating such class, you get your first facade.
Placing orders by phone
When you call a shop to place a phone order, an operator is your facade to all services and departments of the shop. He or she provides a simple interface to the ordering system, payments, and delivery services.
Facade provides convenient access to a particular part of the subsystem's functionality. It knows where to direct the client request and how to prepare all the moving parts.
Additional facades can be created to divide responsibilities and prevent growing an original facade into yet another complex structure. Additional facades can be used either by Clients or other Facades.
Complex subsystem contains dozens of classes. To make them do something meaningful, you have to know their implementation details, the initialization order and lots of other things.
Note that subsystem classes are not aware of the Facade's existence and work with each other directly.
Client uses Facade instead of calling the Subsystem objects directly.
In this examples, the Facade simplifies interaction with a complex video conversion framework. The Facade is a single class with a single public method that handles all the complexity of configuring the right classes of the framework and retrieving result in a correct format.
This way the Facade pattern shields client code from the complexity, keeps it clean and lean.
// Some classes of a complex 3rd-party video conversion framework. We don't // control that code, therefore can't simplify it. class VideoFile // ... class OggCompressionCodec // ... class MPEG4CompressionCodec // ... class CodecFactory // ... class BitrateReader // ... class AudioMixer // ... // To defeat the complexity, we create a Facade class, which hides all of the // framework's complexity behind a simple interface. It is a trade-off between // functionality and simplicity. class VideoConvertor is method convertVideo(filename, format):File is file = new VideoFile(filename) sourceCodec = new CodecFactory.extract(file) if (format == "mp4") distinationCodec = new MPEG4CompressionCodec() else distinationCodec = new OggCompressionCodec() buffer = BitrateReader.read(filename, sourceCodec); result = BitrateReader.convert(buffer, distinationCodec); result = (new AudioMixer()).fix(result); return new File(result) // Application classes don't depend on a billion classes provided by the complex // framework. Also, if you happen to decide to switch framework, you will only // need to rewrite the facade class. class Application is method main() is convertor = new VideoConvertor(); mp4video = convertor.convertVideo("youtubevideo.ogg", "mp4")
When you need to have a simple but limited interface to a complex subsystem.
Often subsystems get more complex over time. Even applying design patterns often leads to creating more classes. The subsystem may become more flexible and easier to reuse in different contexts, but the amount of boilerplate code it requires also grows. The Facade attempts to fix it by providing access to a fraction of a subsystem that fits most client needs.
When you want to structure a subsystem into layers.
Create facades to define the entry points to each level of a subsystem. If multiple subsystems depend on each other, you can limit the coupling by requiring subsystems to communicate only through facades.
How to Implement
Check whether it is possible to simplify the interface of communication with a complex subsystem.
You're on the right track if this interface will make client free of subsystem dependency.
Create a facade class and describe this interface in it. It has to direct client calls to the appropriate objects of the subsystem. Facade should take care of correct subsystem initialization. Usually, this code lives inside the facade constructor. Lazy initialization may also be useful.
You'll get a full benefit if client code would only work with the facade. In this case, the client will be protected from all changes in the subsystem code. For example, when a library's code gets updated, you'll only need to fix a facade.
If the facade becomes monstrous, think of extracting new refined facades.
Pros and Cons
- Isolates clients from subsystem components.
- Minimizes coupling between client code and subsystem.
- Facade risks becoming a "god object", coupled to all application classes.
Relations with Other Patterns
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.
Facade is similar to Proxy in that it buffers a complex entity and also initializes it. Unlike the Facade, the Proxy pattern has the same interface as its service object, which makes them interchangeable.