Bridge Design Pattern:
[This article has been created from a presentation that was created by my wife-Anita. Special thanks to Anita for facilitating the presentation.]
Definition: Decouple an abstraction from its implementation so that both can vary independently
You will find many articles describing the theory about using Bridge Design Pattern using c# .net. Many articles including wiki has already listed down possible usage of this design pattern. I will simply start with a problem statement and we will see how this problem can be achieved.
Here is the class diagram of my vacation planner (The problem statement) and the code.
Here is the code
using System;
using System.Collections.Generic;
using System.Text;
namespace Agency
{
class
Program
{
static
void Main(string[] args)
{
TravelManager tm = new
TravelManager();
utilize(tm);
FoodManager fm = new
FoodManager();
utilize(fm);
//fm.PayBill();
GuideManager gm= new
GuideManager();
utilize(gm);
Console.ReadKey();
}
public
static
void utilize(AgencyManager am)
{
am.Engage();
am.Release();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Agency
{
abstract
class
AgencyManager
{
public
abstract
void Engage();
public
abstract
void Release();
//public abstract void PayBill();
//public void PayBill()
//{
// Console.WriteLine("Amount debited to a/c");
//}
}
class
TravelManager : AgencyManager
{
public
override
void Engage()
{
TravelController.BookVehicle();
}
public
override
void Release()
{
TravelController.ReleaseVehivle();
}
//public override void PayBill()
//{
// Console.WriteLine("Amount debited to a/c");
//}
}
class
FoodManager : AgencyManager
{
public
override
void Engage()
{
FoodController.OrderFood();
}
public
override
void Release()
{
FoodController.FinishFood();
}
}
class
GuideManager : AgencyManager
{
public
override
void Engage()
{
GuideController.HireGuide();
}
public
override
void Release()
{
GuideController.DeHireGuide();
}
//public override void PayBill()
//{
// Console.WriteLine("Amount debited to a/c");
//}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Agency
{
public
class
TravelController
{
public
static
void BookVehicle()
{
Console.WriteLine("Vehicle booked");
}
public
static
void ReleaseVehivle()
{
Console.WriteLine("Vehicle Released");
}
}
public
class
FoodController
{
public
static
void OrderFood()
{
Console.WriteLine("Food ordered.");
}
public
static
void FinishFood()
{
Console.WriteLine("Food finished.");
}
}
public
class
GuideController
{
public
static
void HireGuide()
{
Console.WriteLine("Guide hired.");
}
public
static
void DeHireGuide()
{
Console.WriteLine("Guide dehired.");
}
}
}
As listed down in the above code and class diagram I have a simple abstract class and 3 implementations. Now the problem starts when I start exploring the application more. Let's say I have to add a new method PayBill which are required only for two implementations i.e for TravelManager and GuideManager. However I want to keep the third implementation FoodManager away from this method. Since all of them are implementing the same abstract class, I cannot add this method at the abstract level since in that case it will compulsory for FoodManager to implement that method which I don't want. The other way is to add the method at individual classes. However that will invite unnecessary duplication of code.
There can be someother solution to this problem but we will see how to handle such situation using the Bridge Design Pattern.
So here is the class diagram and the resulting code which shows us how we can resolve this issue.
And here is the code
using System;
using System.Collections.Generic;
using System.Text;
namespace BridgeDesignPattern
{
class Program
{
static void Main(string[] args)
{
PaidAgencies agency = new PaidAgencies();
agency.AgencyManager = new TravelManager();
agency.Engage();
agency.Release();
agency.PayBill();
agency.AgencyManager = new GuideManager();
agency.Engage();
agency.Release();
agency.PayBill();
AddOnAgecies freeagency = new AddOnAgecies();
freeagency.AgencyManager = new FoodManager();
freeagency.Engage();
freeagency.Release();
freeagency.Reimburse();
Console.ReadKey();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace BridgeDesignPattern
{
/// <summary>
/// Abstraction
/// </summary>
public abstract class AgencyAbstraction
{
AgencyManager agencyManager;
public AgencyManager AgencyManager
{
get { return agencyManager; }
set { agencyManager = value; }
}
public abstract void Engage();
public abstract void Release();
}
/// <summary>
/// Refined abstraction
/// </summary>
public class PaidAgencies : AgencyAbstraction
{
public override void Engage()
{
AgencyManager.Engage();
}
public override void Release()
{
AgencyManager.Release();
}
public void PayBill()
{
Console.WriteLine("Amount Debited to Account");
}
}
/// <summary>
/// Refine abstraction 2
/// </summary>
public class AddOnAgecies : AgencyAbstraction
{
public override void Engage()
{
AgencyManager.Engage();
}
public override void Release()
{
AgencyManager.Release();
}
public void Reimburse()
{
Console.WriteLine("Amount credited to Account");
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace BridgeDesignPattern
{
/// <summary>
/// This is implementor
/// </summary>
public abstract class AgencyManager
{
public abstract void Engage();
public abstract void Release();
}
/// <summary>
/// This is concrete implementor
/// </summary>
public class TravelManager : AgencyManager
{
public override void Engage()
{
TravelController.BookVehicle();
}
public override void Release()
{
TravelController.ReleaseVehicle();
}
}
/// <summary>
/// This is concrete implementor
/// </summary>
class FoodManager : AgencyManager
{
public override void Engage()
{
FoodController.OrderFood();
}
public override void Release()
{
FoodController.FinishFood();
}
}
/// <summary>
/// This is concrete implementor
/// </summary>
class GuideManager : AgencyManager
{
public override void Engage()
{
GuideController.HireGuide();
}
public override void Release()
{
GuideController.DeHireGuide();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace BridgeDesignPattern
{
/// <summary>
///
/// </summary>
public class TravelController
{
public static void BookVehicle()
{
Console.WriteLine("Vehicle booked");
}
public static void ReleaseVehicle()
{
Console.WriteLine("Vehicle Released");
}
}
public class FoodController
{
public static void OrderFood()
{
Console.WriteLine("Food ordered");
}
public static void FinishFood()
{
Console.WriteLine("Food finished");
}
}
public class GuideController
{
public static void HireGuide()
{
Console.WriteLine("Guide hired");
}
public static void DeHireGuide()
{
Console.WriteLine("Guide dehired");
}
}
}
As you can see now we can add methods at the Abstraction level whereas clients are using the refined abstraction. This way we are free to make changes at the abstract level as well as at the implementation level.
I Hope this explains the bridge design pattern clearly. Please feel free to comment on this article in case you have any queries/suggestions/comments. I have this source code along with a presentation in a zip and I can provide the same free of cost. Email me at SubhashD987[AT]mail.com
Enjoy programming…
Special thanks to Subhash for giving place in his blog for my presentation
ReplyDeleteNice article on C#.net
ReplyDeleteHope to see more from you.
It would be great if you could write the article about vb.net interfacing.
I'm in search of detailed description about it,with small examlpes.