Wednesday 8 September 2010

C++ example for Bridge Design Pattern

The Bridge pattern decouples an abstraction from its implementation, so that the two can vary independently. A household switch controlling lights, ceiling fans, etc. is an example of the Bridge. The purpose of the switch is to turn a device on or off. The actual switch can be implemented as a pull chain, simple two position switch, or a variety of dimmer switches.


Differences between Bridge, Adapter and other patterns
  • Adapter makes things work after they’re designed; Bridge makes them work before they are.
  • Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together.
  • State, Strategy, Bridge (and to some degree Adapter) have similar solution structures. They all share elements of the “handle/body” idiom. They differ in intent - that is, they solve different problems.
  • The structure of State and Bridge are identical (except that Bridge admits hierarchies of envelope classes, whereas State allows only one). The two patterns use the same structure to solve different problems: State allows an object’s behavior to change along with its state, while Bridge’s intent is to decouple an abstraction from its implementation so that the two can vary independently.
  • If interface classes delegate the creation of their implementation classes (instead of creating/coupling themselves directly), then the design usually uses the Abstract Factory pattern to create the implementation objects.
The frequency of use of Bridge is medium and the UML diagram is as follows:



Example of Bridge as follows:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Bridge is part of Structural Patterns
//Structural Patterns deal with decoupling the interface and implementation of classes and objects
//Bridge separates an object's interface from its implementation


#include<iostream>
#include<string>
#include<list>

using namespace
std;

//The 'Implementor' abstract class
class DataObject
{

public
:
virtual
void NextRecord()=0;
virtual
void PriorRecord()=0;
virtual
void AddRecord(string name)=0;
virtual
void DeleteRecord(string name)=0;
virtual
void ShowRecord()=0;
virtual
void ShowAllRecords()=0;
};


//The 'ConcreteImplementor' class
class CustomersData : public DataObject
{

public
:
CustomersData()
{

current_ = 0;
}

void
NextRecord()
{

if
(current_ < (int)(customers_.size() - 1))
current_++;
}

void
PriorRecord()
{

if
(current_ > 0)
current_--;
}

void
AddRecord(string name)
{

customers_.push_back(name);
}

void
DeleteRecord(string name)
{

list<string>::iterator it = customers_.begin();
while
(it != customers_.end())
{

if
(*it == name)
{

customers_.erase(it);
break
;
}
++
it;
}
}

void
ShowRecord()
{

list<string>::iterator it = customers_.begin();
for
(int i = 0; i < current_; i++, ++it);
cout<<*it<<endl;
}

void
ShowAllRecords()
{

list<string>::iterator it = customers_.begin();
while
(it != customers_.end())
{

cout<<*it<<endl;
++
it;
}
}

private
:
int
current_;
list<string> customers_;
};


//The 'Abstraction' class
class CustomersBase
{

public
:
CustomersBase(string group):group_(group){};
void
SetDataObject(DataObject* value)
{

dataObject_ = value;
}

DataObject* GetDataObject(void)
{

return
dataObject_;
}

virtual
void Next()
{

dataObject_->NextRecord();
}

virtual
void Prior()
{

dataObject_->PriorRecord();
}

virtual
void Add(string customer)
{

dataObject_->AddRecord(customer);
}

virtual
void Delete(string customer)
{

dataObject_->DeleteRecord(customer);
}

virtual
void Show()
{

dataObject_->ShowRecord();
}

virtual
void ShowAll()
{

cout<<"Customer Group : "<<group_<<endl;
dataObject_->ShowAllRecords();
}

protected
:
string group_;
private
:
DataObject* dataObject_;
};


//The 'RefinedAbstraction' class
class Customers : public CustomersBase
{

public
:
Customers(string group) : CustomersBase(group) {};
//overriding
void ShowAll()
{

cout<<"\n------------------------------------"<<endl;
CustomersBase::ShowAll();
cout<<"------------------------------------"<<endl;
}
};


//Main
int main()
{

//Create RefinedAbstraction
Customers* customers = new Customers("London");

//Set ConcreteImplementor
CustomersData* customersData = new CustomersData();
DataObject* dataObject = customersData;

customersData->AddRecord("Tesco");
customersData->AddRecord("Sainsburys");
customersData->AddRecord("Asda");
customersData->AddRecord("Morrisons");
customersData->AddRecord("Lidl");
customersData->AddRecord("Co-op");

customers->SetDataObject(dataObject);

//Exercise the bridge
customers->Show();
customers->Next();
customers->Show();
customers->Next();
customers->Show();
customers->Add("M&S");

customers->ShowAll();


return
0;
}



The Output is as follows:



For more information see:
http://www.dofactory.com/Patterns/PatternBridge.aspx
http://sourcemaking.com/design_patterns/bridge
http://www.vincehuston.org/dp/bridge.html

No comments:

Post a Comment