This is in continuation to the previous post. Please note that this post will be long one, so if you have time keep reading
Its states that “Separating Object’s interface from its actual implementation”.
What the above line means is that, usually OO developers try to keep a clean separation between the interface and its implementation. This allows us to write flexible code through out our complex systems ensuring the link between the components are not too strong so that decoupling them or adding/modifying the same component in the future is not tedious.
As the name itself says that it acts as bridge between components in a complex system. The specialty of this bridge is that, more number of components can be plugged into this bridge and made to work, without modifying or altering any component. Only the bridge needs a bit of alterations which is very much efficient than modifying other connected components.
Now i am sure, you shall be in a confusion that it almost sounds like Adapter pattern earlier i explained. I would say just hold your doubts/curiosity for now, since my last post on this series will talk about the same.
As per above said lines and by its definition, it acts as a bridge. So hence its very much helpful for us in:
- Connecting many different components together, where in the implementation and abstraction/interface can vary independently. In many real world situation we shall encounter situations like many components are getting developed or undergoing frequent changes in itself due to many reasons. In such cases, coupling them together and building systems are really a tedious process. Hence to ease the process of coupling these independently varying components in a better way this pattern is used.
- Since we aimed at loose coupling the interface/abstraction with its implementation, hence we gain a big leap in advantage w.r.t hard binding. Basically in modern-day programming the components needs to be more flexible in nature. And it should have very less dependency as well. So loose binding is a way to go.
- Since the components vary independently, if this patterns wasn’t used then we would have gone for long inheritance tree implementation in order to have features supported in the components which vary independently at any time.
Lets take a look at the example of drawing a rectangle for a Normal window or for a dialog box. Basically all window frame which needs to be displayed on-screen are in rectangle shape (at least by default). Now assume that i have few different platforms where in i need to display this rectangle box based on which type of window. But unfortunately the platforms are very different in nature, so the way i am supposed to draw the rectangle for this window types is also quite different. Later point of time, more number of platforms viz. Linux, windows, Mac, etc. could be added or even more number of window types also could be added.
So lets take a look at the code now:
As per the above code, i have created a base class which has few data members in the base class which is abstract. Now since i have many window types, hence there are many sub classes as per the window type viz. NormalWindow, DialogWindow, etc.
If you see the code, the sub classes ctor takes a parameter which specifies which platform specific frame should be drawn. These subclasses also override DrawRectangle() method since the way the window frame has to be drawn is different.
Now i have pushed the creation of platform specific object to the abstract class method GetOSTypeObject(), so that multiple implementation is not required in sub classes. Yes i could have made this method sealed, but that’s left to the scenario in your application.
You could argue that any new requirement for a window type needs alteration to this class. But hey is it not Open Closed principle we are following? 🙂 But yes there is a bit of modification required if there is a new platforms are added viz. OS2, WebOS, BSDUnix, Solaris Unix, etc. But i can say that you can solve that too by using another pattern here, perhaps abstract factory. By doing so, you shall end up in a big soup called Patterns of Patterns.
As said already, too much of pattern fever shall make you go crazy and make your code more complex. So try to be a bit soft on this, after all i think patterns are like sexy girls the more you think about them the more you get addicted to them 😉
Lets look at the other side of the component which also gets changed frequently viz. Platforms.
As this phase of the component too, i am having many subclasses for each specific platforms. One thing you need to observe here is that the implementation details is hidden from every one else. The requester object doesn’t even know how actually the line is drawn by the platform it is asking. So as already said at run time every object is just delegating a request call to an unknown object which does some job and gets the result back.
Now lets see the usage code part:
I think the usage code is self-explanatory.
There are many examples in real world usage:
- In House, Electric appliances vs Switch. Where in you can find many appliances which varies like fans, tv, refrigerators, AC, etc. but at the same time you switch on them using a switch which also varies in many shapes although their functionality is same. These switches can come in Toggle, up and down, illuminated, dimmer, etc.
- Similar to above code example i gave out, you can also use this pattern in representing Text file storage in various platforms. Because each platforms handle text in different way like char to end a line, format of the text storage, compression used if any, etc. On the same way, the type of text files such as normal simple text files, RTF, etc.
Well, that’s all dear friend i can talk about this pattern. I am sorry if it’s too lengthy, but i wanted to make every point clear.
Look out for my next post in continuation to this.
P.S: Your valuable comments, votes are well appreciated.