Background
Again, my favorite place - Elizabeth's daycare center.
In Elizabeth's daycare center, all teachers are very friendly and try to make friends with all the kids.
At first, it's very hard to build a relationship between a new kid and a new teacher since they have never met each other. In order to allow the teacher and the kid to communicate with each other, we somehow need to build a communication path to allow the teacher/director (anyone who wants to be a communicator) to communicate with the kid.
A teacher (Communicator object) can talk to any kid (talkable object), and a kid should also allow any teacher (Communicator object) to start talking to him/her as well. Just like how printers work with computers. If we have a USB cable (bridge), then we can connect any printer to any computer to start printing. It really doesn't matter if it's a laser printer or a color printer, either Windows PC or Mac. Because we know all the printers will allow the computers to print, makes sense?
Introduction
The Bridge Pattern could help us to separate the contract and implementation in two independent areas. We could use interface in C# to build our contract. The contract will only provide/list the functionality, but leave the implementation to the implementer to handle. So the contract can be used as a bridge within other classes, and it allows other classes to consume the concrete implementer without knowing anything about the details.
This article introduces an implementation of how we use the bridge pattern to our daycare center.
Bridge Design Pattern Structure
Class Diagram
Implementation Code
Abstraction Class
ICommunicator
ICommunicator
is an interface that will be inherited by other classes when those classes want to be able to communicate to an ITalkable
object. In ICommunicator
class, we have ITalkable
object defined and it could allow us to use all the functionality from an Italkable
object. An Italkable
object acts as a bridge here to let ICommnucator
object consume it.
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace BridgeDesignPattern
{
public interface ICommunicator
{
ITalkable objToTalk { get; set; }
void StartChatting();
}
}
}
Teacher
Teacher
class, is a RefinedAbstraction
class, it actually implements the details for StartChatting()
methods. In the teacher class, I cast the ITalkable
object to a Kid
object in case I need to use some properties from the Kid
class. However, we don't have to do the casting here since we only care about the ITalkable
functionality.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace BridgeDesignPattern
{
public class Teacher : ICommunicator
{
Kid aKid = new Kid();
#region ICommunicator Members
public ITalkable objToTalk
{
get
{
return aKid;
}
set
{
aKid = (Kid)value;
}
}
public void StartChatting()
{
Console.WriteLine("What's your name?");
aKid.TellMeAboutName();
Console.WriteLine("How old are you?");
aKid.TellMeAboutAge();
Console.WriteLine("What's your favor food");
aKid.TellMeAboutFavorFood();
string name = aKid.Name;
}
#endregion
}
}
}
Director
Same as Teacher
, another ConcreteAbstraction
class. It directly uses the ITalkable
object (aKid
) to implement the StartChatting()
method. No casting process here just to show a little differences with Teacher
's Startchatting()
method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com.BridgeDesignPattern
{
public class Director : ICommunicator
{
ITalkable aKid;
#region ICommunicator Members
public ITalkable objToTalk
{
get
{
return aKid;
}
set
{
aKid = value;
}
}
public void StartChatting()
{
Console.WriteLine("Hi , can your tell me your name?");
aKid.TellMeAboutName();
Console.WriteLine("Hi , can you tell my your age?");
aKid.TellMeAboutAge();
}
#endregion
}
}
Implementor Class
ITalkable
ITalkable
interface lists all the contract methods/functionality that a talkable class must have. A class that needs to be eligible to be talked by a Communicator
object needs to inherit the ITalkable
interface.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace BridgeDesignPattern
{
public interface ITalkable
{
void TellMeAboutName();
void TellMeAboutAge();
void TellMeAboutFavorFood();
}
}
}
Kid
Kid
class inherits from the ITalkable
interface to make itself talkable. It implements each ITalkable
method by its own rules. In this case study, I only define one Kid
class that inherits from ITalkable
interface. Actually, any class can inherit the ITalkable
interface to make itself able to be talked by any Communicator
object.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace BridgeDesignPattern
{
public class Kid : ITalkable
{
public string Name { get; set; }
public int Age { get; set; }
public string FavorFood { get; set; }
#region ITalker Members
public void TellMeAboutName()
{
Console.WriteLine("My name is {0}", Name);
}
public void TellMeAboutAge()
{
Console.WriteLine("I am {0} years old", Age.ToString());
}
public void TellMeAboutFavorFood()
{
Console.WriteLine("My favor food is {0}", FavorFood);
}
#endregion
}
}
}
Client App
From the client side, I create two kids (Elizabeth
& Ammie
) as our ITalkable
objects, and also create a Teacher
and a Director
as our ICommunicator
objects.
Let both Teacher
and Director
start talking to the two kids, we will see both Elizabeth
& Ammie
are able to answer the questions from the two ICommunicator
objects.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using www.askbargains.com.BridgeDesignPattern;
namespace www.askbargains.com
{
namespace Client
{
class Program
{
static void Main(string[] args)
{
Teacher Megan = new Teacher();
Director Lisa = new Director();
Kid Elizabeth = new Kid();
Elizabeth.Name = "Elizabeth";
Elizabeth.Age = 3;
Elizabeth.FavorFood = "Chicken Nuggets";
Kid Ammie = new Kid();
Ammie.Name = "Ammie";
Ammie.Age = 4;
Ammie.FavorFood = "French Fries";
Console.WriteLine("Miss Megan starts talking to Elizabeth");
Megan.objToTalk = Elizabeth;
Megan.StartChatting();
Console.WriteLine();
Console.WriteLine("Director Lisa starts talking to Ammie");
Lisa.objToTalk = Ammie;
Lisa.StartChatting();
Console.WriteLine();
Console.WriteLine("Miss Megan starts talking to Ammie");
Megan.objToTalk = Ammie;
Megan.StartChatting();
Console.WriteLine();
Console.WriteLine("Director Lisa starts talking to Elizabeth");
Lisa.objToTalk = Elizabeth;
Lisa.StartChatting();
Console.Read();
}
}
}
}
Once we start our client app, you will see all that no matter who wants to talk to the kids, the kids will give the correct answer to the communicators. Cool!
Conclusion
From this article, I demonstrated how we can use the Bridge Pattern to achieve the implementation for a communication system in Elizabeth's daycare. I also use the daycare center for the Prototype Design pattern in my other articles as well.
History
- 30th September, 2009: Initial post