Facade provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher level interface that makes the subsystem easy to use.
Facade pattern works on principle of least knowledge.
A Facade not only simplifies an interface, it also decouples a client from subsytem of components. Using Facade Pattern you can take a complex subsystem and make it easier to use by implementing a Facade class that provides resonable interface.
Need for Facade
For Example,Let us think we have subsytem containing Gate, GarageDoors, CarLock, Lights etc.. Now when we leave home we have to following:
door.open();
lights.off();
door.close();
garageDoor.open();
carLock.unlock();
gate.open();
garageDoor.close();
gate.close();
This is a small subsystem, but consider you have bungalow, things get more complicated. Not only this, when the person comes back , he has to do following things:
gate.open();
garageDoor.open();
carLock.lock();
door.open();
lights.on();
gate.close();
garageDoor.close();
door.close();
Instead of doing all that stuff and making lots of object in our main class, we supply all these components to our facade class, which deals with these components and solve these problems. Now we will be having a single iterface which will do simplify the subsystem for us:
public class HomeFacade{
Gate gate;
GarageDoor garageDoor;
CarLock carLock;
Lights lights;
MainDoor door;
public HomeFacade(Gate gate,GarageDoor garageDoor,CarLock carLock,Lights lights,MainDoor door){
this.gate = gate;
this.garageDoor = garageDoor;
this.carLock = carLock;
this.lights = lights;
this.door = door;
}
public void reachHome(){
gate.open();
garageDoor.open();
carLock.lock();
door.open();
lights.on();
gate.close();
garageDoor.close();
door.close();
}
public void leaveHome(){
door.open();
lights.off();
door.close();
garageDoor.open();
carLock.unlock();
gate.open();
garageDoor.close();
gate.close();
}
}
The Facade still leaves the subsystem accessible to be used directly. If you need the advanced functionality of the subsystem classes, they are avilable for your use. (As Facade doesn't encapsulate the subsystem classes, but it provides a simplified interface)
Facade is free to add its own specialization in addition to making use of subsystem.
For a subsystem, we can have number of Facades.
Design Principle behind Facade pattern :
Priciple of least knowledge : When you are designing a system, for any object be careful of the number of classes it interacts with and also how it interacts with those classes. Also known as law of Demeter.
This principle prevents us from creating designs that have a large number of classes coupled together so that changes in one part of the system cascade to other parts. when you build a lot of dependencies between many classes, you are building a fragile system that is costly to maintain and complex for others to understand.
But how to implement this design priciple?
Take any object. Now from any method in that object, we should only invoke methods that belong to
1. The Object itself
2. Objects passed in as a parameter to the methods
3. Any object that method creates and instantiates.
4. Any components of objects. (Has-A relationship)
(Dont call methods on objects that were returned from calling other methods)
Example :
Without principle :
public float applyForJob(){
Agency agency = company.getAgency();
return agency.searchJob();
}
Here we are dependent on Agency Class also
With principle:
public float applyForJob(){
return company.searchJob();
}
This reduces the number of classes we are dependent on.
Primary benifit is that the calling method doesn't need to understand structural makeup of the object it's invoking methods upon.
The obvious disadvantage of using this principle is that we must create many methods that only forward method calls to the containing classes internal components. This can contribute to a large and cumbersome public interface.
An alternative to this principle or variation on its implementation, is to obtain a reference to an object via a method call, with the restriction that any time this is done, the type of reference obtained is always an interface datatype. As we are binding ourselves with directly to the concrete implementation of a complex object, but instead we are depending on abstractions of which the complex object is composed.
A very nice example of the above approach is java.sql.ResultSet interface.
After an SQL statement has been executed, Java stores results in a ResultSet Object. One of our options at this point is to query this resultset object and obtain metainformation pertaining to this set of data. The class that contains this metadata is ResultSetMetaData class and it's contained with resultset class. We cant directly obtain reference of this class, but instead would call methods on the ResultSet which subsequently forward these requests to ResultSetMetaData Class. This would results in explosion of methods on ResultSet class. Therefore getResultSetMetaData() method on ResultSet would does return a reference to ResultSetMetaData. However as ResultSetMetaData is an interface we are not bound to any concrete implementation contained within resultset.
Difference between Adapter pattern and facade Pattern:
Adapter Pattern changes the interface of one or more classes into one interface that a client is expecting while a Facade may provide a simplified interface to a single class with a very complex interface.
Facade and Adapter may wrap multiple classes but facade's intent is to simplify and adapter's intent is to convert the interface to something different.
Hope it will be useful.
No comments:
Post a Comment