Bridge Pattern (Handle/Body Idiom)
OK, OK agreed that I have been doing a sloppy work from last two posts but I am sure I am gonna make up in this post. Here I am going to tell a little about the Bridge pattern. Well when we think about bridge pattern the first thing that come to our mind is “ it is some kind of bridge between two different implementations” Well not true, entirely not true. This is the task of Adapter pattern which we are going to discuss sometime later. But to talk about bridge, this pattern is designed up-front to let the abstraction and the implementation vary independently.
Ohh, too harsh, well lets start one by one lets look ate the booking definition of bridge once.
“Decouple an abstraction from its implementation so that the two can vary independently.”
So I hope u understood the pattern, good luck see you next time.
Just kidding, lets start post mortem of this definition as we do always. We all know that C++, by default doesn’t do a good job to support data abstraction.
• A class defines the data members of its instances. These members are defined private so nobody can access them but still they are actually present in the header file of the class.
• The client code that is using this class will compile only if it has access to the definitions of the type of data members. And if the definition of any of these member objects are changed the client code also need to be recompiled.
Since the interface are more stable (i.e less probability of getting changed) than the implementation it sounds like a good idea to put the interfaces of a class separate from the implementation.
OK lets assume we are going to develop a game. (I am a big fan of Jhon Carmack. He is the one who made all the difference in my life by bringing 3D games in this world)
Ok so lets say we are going to develop a game and we have to write a Man class. The approach without using the bridge pattern will look like.
The ManBody class:
#pragma once
#include
class ManBody
{
public:
ManBody(void)
{
std::cout<<"Creating a man\n"; } ~ManBody(void) { std::cout<<"Killing a man\n"; } void GoRight() { std::cout<<"Man moving right\n"; } void GoLeft() { std::cout<<"Man moving left\n"; } }; The Controller class: #pragma once #include “ManBody.h” class ManController { public: ManHandle(void); ~ManHandle(void); void MoveRight(); void MoveLeft(); private: ManBody man; }; And then in the functions MoveRight and MoveLeft we will actually Move the man (or let the client use ManBody directly, but that is equally problematic). This look simple but imagine if our Man has to be the protagonist and do a hell lot of jobs other than moving left and right than I guess whenever we change the ManBody this Man controller will also get changed. Also since The ManBody is also visible to the Client who is using it. It also need to get recompiled. So how to separate out the interface from implementation is the question. The answer is Bridge pattern. Now let us try to understand the crux of bridge pattern from C++ point of view. • We are going to separate out the interface (call it handle) from the implementation (call it body) • We will not include the ManBody header file in the ManHandle(sounds good isn’t it) instead we are gonna keep a pointer to the actual implementation (body) in our handle class and just do a forward declaration in it. Ok so lets first try and create our handle class. ------------------------------ManHandle.hpp---------------------- #pragma once class ManBody; class ManHandle { public: ManHandle(void); ~ManHandle(void); void MoveRight(); void MoveLeft(); private: ManBody *PmanImpl; }; See this handle need not include the ManBody. Now this code need not recompiled when we are changing the implementation of of ManBody and so the client code who actually uses it. The implementation of the handle, on the contrary use the ManBody class like ------------------------------ManHandle.cpp---------------------- #include "StdAfx.h" #include "ManHandle.h" #include "manbody.h" ManHandle::ManHandle(void) : PmanImpl(0) { PmanImpl = new ManBody(); } ManHandle::~ManHandle(void) { delete PmanImpl; PmanImpl = 0; } void ManHandle::MoveRight() { PmanImpl->GoRight();
}
void ManHandle::MoveLeft()
{
PmanImpl->GoLeft();
}
And the client code will look like
// Handle-Body.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "manhandle.h"
int _tmain(int argc, _TCHAR* argv[])
{
ManHandle *handle = new ManHandle;
handle->MoveLeft();
handle->MoveRight();
delete handle;
getchar();
return 0;
}
See the interface for moving the man and the client code now are totally independent of the implementation of the ManBody class. Isn’t that what we wanted.
Now lets try and visualize this pattern {figure from GoF book}

The benefits that we are getting from this pattern are
• Decoupling interface and implementation
• Improved extensibility. You can extend the Abstraction and Implementer hierarchies independently.
• Hiding implementation details from clients.
and on the concluding note lets find out where we can actually us this pattern
• you want run-time binding of the implementation,
• you have a proliferation of classes resulting from a coupled interface and numerous implementations,
• you want to share an implementation among multiple objects,
• you need to map orthogonal class hierarchies.
OK, OK agreed that I have been doing a sloppy work from last two posts but I am sure I am gonna make up in this post. Here I am going to tell a little about the Bridge pattern. Well when we think about bridge pattern the first thing that come to our mind is “ it is some kind of bridge between two different implementations” Well not true, entirely not true. This is the task of Adapter pattern which we are going to discuss sometime later. But to talk about bridge, this pattern is designed up-front to let the abstraction and the implementation vary independently.
Ohh, too harsh, well lets start one by one lets look ate the booking definition of bridge once.
“Decouple an abstraction from its implementation so that the two can vary independently.”
So I hope u understood the pattern, good luck see you next time.
Just kidding, lets start post mortem of this definition as we do always. We all know that C++, by default doesn’t do a good job to support data abstraction.
• A class defines the data members of its instances. These members are defined private so nobody can access them but still they are actually present in the header file of the class.
• The client code that is using this class will compile only if it has access to the definitions of the type of data members. And if the definition of any of these member objects are changed the client code also need to be recompiled.
Since the interface are more stable (i.e less probability of getting changed) than the implementation it sounds like a good idea to put the interfaces of a class separate from the implementation.
OK lets assume we are going to develop a game. (I am a big fan of Jhon Carmack. He is the one who made all the difference in my life by bringing 3D games in this world)
Ok so lets say we are going to develop a game and we have to write a Man class. The approach without using the bridge pattern will look like.
The ManBody class:
#pragma once
#include
class ManBody
{
public:
ManBody(void)
{
std::cout<<"Creating a man\n"; } ~ManBody(void) { std::cout<<"Killing a man\n"; } void GoRight() { std::cout<<"Man moving right\n"; } void GoLeft() { std::cout<<"Man moving left\n"; } }; The Controller class: #pragma once #include “ManBody.h” class ManController { public: ManHandle(void); ~ManHandle(void); void MoveRight(); void MoveLeft(); private: ManBody man; }; And then in the functions MoveRight and MoveLeft we will actually Move the man (or let the client use ManBody directly, but that is equally problematic). This look simple but imagine if our Man has to be the protagonist and do a hell lot of jobs other than moving left and right than I guess whenever we change the ManBody this Man controller will also get changed. Also since The ManBody is also visible to the Client who is using it. It also need to get recompiled. So how to separate out the interface from implementation is the question. The answer is Bridge pattern. Now let us try to understand the crux of bridge pattern from C++ point of view. • We are going to separate out the interface (call it handle) from the implementation (call it body) • We will not include the ManBody header file in the ManHandle(sounds good isn’t it) instead we are gonna keep a pointer to the actual implementation (body) in our handle class and just do a forward declaration in it. Ok so lets first try and create our handle class. ------------------------------ManHandle.hpp---------------------- #pragma once class ManBody; class ManHandle { public: ManHandle(void); ~ManHandle(void); void MoveRight(); void MoveLeft(); private: ManBody *PmanImpl; }; See this handle need not include the ManBody. Now this code need not recompiled when we are changing the implementation of of ManBody and so the client code who actually uses it. The implementation of the handle, on the contrary use the ManBody class like ------------------------------ManHandle.cpp---------------------- #include "StdAfx.h" #include "ManHandle.h" #include "manbody.h" ManHandle::ManHandle(void) : PmanImpl(0) { PmanImpl = new ManBody(); } ManHandle::~ManHandle(void) { delete PmanImpl; PmanImpl = 0; } void ManHandle::MoveRight() { PmanImpl->GoRight();
}
void ManHandle::MoveLeft()
{
PmanImpl->GoLeft();
}
And the client code will look like
// Handle-Body.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "manhandle.h"
int _tmain(int argc, _TCHAR* argv[])
{
ManHandle *handle = new ManHandle;
handle->MoveLeft();
handle->MoveRight();
delete handle;
getchar();
return 0;
}
See the interface for moving the man and the client code now are totally independent of the implementation of the ManBody class. Isn’t that what we wanted.
Now lets try and visualize this pattern {figure from GoF book}
The benefits that we are getting from this pattern are
• Decoupling interface and implementation
• Improved extensibility. You can extend the Abstraction and Implementer hierarchies independently.
• Hiding implementation details from clients.
and on the concluding note lets find out where we can actually us this pattern
• you want run-time binding of the implementation,
• you have a proliferation of classes resulting from a coupled interface and numerous implementations,
• you want to share an implementation among multiple objects,
• you need to map orthogonal class hierarchies.
No comments:
Post a Comment