Introduction
This article talks about the facade pattern. When is this pattern useful. This article also presents a rudimentary
approach to implement the facade pattern.
Background
There are some scenarios in our application, we need to work with a series of objects to perform certain task.
For example, If we are writing software for a universal remote and I want to turn off all the devices then I have
few options. First I can manually select each device and turn them off one by one. This was rather a crude approach so
why not automate this inside the remote itself. So I can have a button that will turn off all the devices. Now to
turn off all the devices all I need to so is to push this button. The button press command of this remote will now talk
to all the device controllers and turn them off.
Now if I need the similar functionality to be executed automatically at 12 o'clock in night. Now this timer based
event will also talk to all the devices and stop them all. So the problem here is that in all the scenarios I need
to have this functionality I need to talk to these objects.
There is one more approach in designing this solution. Why not have an object whose responsibility is to stop
all the devices. Now whenever I need to stop all the devices, I need to call this object only. This is exactly the
philosophy behind the facade pattern. GoF defines facade pattern as "Provide a unified interface to a set of interfaces
in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use."
To visualize this pattern:
The important thing to note here is that the facade object is simply providing the set of functionalities in an
easier way. It is not altering the interface of the subsystem. The subsystem classes can still be accessed by the
other parts of the system. The facade will provide the group of functionalities in a single location.
Using the code
To illustrate the facade pattern, Lets try to look into a small example. Lets try to implement a hypothetical
facade object to work with some Windows Phone controller objects. First let me define the problem.
Every morning when I go for jogging, I have to make the following changes in my Windows phone device:
- Turn off the wifi
- Switch on the Mobile Data
- Turn on the GPS
- Turn on the Music
- Start the Sports-Tracker
And after coming back from jogging, follwing needs to be done from my part:
- Share Sports tracker stats on twitter and facebook
- Stop the Sports Tracker
- Turn off the Music
- Turn off the GPS
- Turn off the Mobile Data
- Turn on the wifi
All this is being done manually right now. So to simulate the behavior lets first implement the
subsystem i.e. the dummy controller classes.
class GPSController
{
bool isSwitchedOn = false;
public bool IsSwitchedOn
{
get
{
return isSwitchedOn;
}
set
{
isSwitchedOn = value;
DisplayStatus();
}
}
private void DisplayStatus()
{
string status = (isSwitchedOn == true) ? "ON" : "OFF";
Console.WriteLine("GPS Switched {0}", status);
}
}
Other controllers like MobileDataController
, MusicController
, WifiController
are also implemented in a similar way.
Now to emulate the App behavior.
class SportsTrackerApp
{
public void Start()
{
Console.WriteLine("Sports Tracker App STARTED");
}
public void Stop()
{
Console.WriteLine("Sports Tracker App STOPPED");
}
public void Share()
{
Console.WriteLine("Sports Tracker: Stats shared on twitter and facebook.");
}
}
So right now with What I am doing is changing all the settings manually and then starting the App manually.
Which can be visualized in form of code as:
static void Main(string[] args)
{
GPSController gps = new GPSController();
MobileDataController data = new MobileDataController();
MusicController zune = new MusicController();
WifiController wifi = new WifiController();
wifi.IsSwitchedOn = false;
data.IsSwitchedOn = true;
gps.IsSwitchedOn = true;
zune.IsSwitchedOn = true;
SportsTrackerApp app = new SportsTrackerApp();
app.Start();
Console.WriteLine();
app.Share();
app.Stop();
zune.IsSwitchedOn = false;
gps.IsSwitchedOn = false;
data.IsSwitchedOn = false;
wifi.IsSwitchedOn = true;
}
Note: All this is to emulate the behavior of my Windows Phone. If we run this application the output
will be:
Now I have to write myself a facade application that will do all this for me internally. I will write an
class that will simply expose two methods like StartJogging
and StopJogging
to me. internally it will
take care of doing all these activities. So let me write a facade now:
class MyJoggingFacade
{
GPSController gps = new GPSController();
MobileDataController data = new MobileDataController();
MusicController zune = new MusicController();
WifiController wifi = new WifiController();
SportsTrackerApp app = null;
public void StartJogging()
{
wifi.IsSwitchedOn = false;
data.IsSwitchedOn = true;
gps.IsSwitchedOn = true;
zune.IsSwitchedOn = true;
app = new SportsTrackerApp();
app.Start();
}
public void StopJogging()
{
app.Share();
app.Stop();
zune.IsSwitchedOn = false;
gps.IsSwitchedOn = false;
data.IsSwitchedOn = false;
wifi.IsSwitchedOn = true;
}
}
Now the same functionality could be achieved by doing a minimal amount of manual work from the user.
static void Main(string[] args)
{
MyJoggingFacade facade = new MyJoggingFacade();
facade.StartJogging();
Console.WriteLine();
facade.StopJogging();
}
Before summing up let us compare the class diagram of this implementation with the facade pattern:
Note: The sample application talks about Apps and controllers. The real world implementation of these
must be in form of separate application. We have considered all of them as classes of single application
just for illustrating the facade pattern. If we actually implement such an application that will also be a
facade but it will be a facade application rather than implementation of facade pattern.
Point of interest
In this article we have discussed about facade pattern. Often this pattern is confused with adapter pattern
but in fact adapter pattern actually presents an altered interface of a system to the client and the original
interface is not accessible. The facade pattern on the other hand provides a simpler interface of the subsystem.
The original objects/system can still be accessed. I hope this has been informative.
History
- 22 October 2012: First version.