Support us .Net Basics C# SQL ASP.NET ADO.NET MVC Slides C# Programs Subscribe Buy DVD

Bridge Design Pattern

Suggested Videos
Part 15 - ProtoType Design Pattern Implementation - Text - Slides
Part 16 - Structural Design Patterns Introduction - Text - Slides
Part 17 - Adapter Design Pattern - Text - Slides

In this video we will discuss 
  • What is Bridge Design Pattern
  • Implementation Guidelines of Bridge design pattern
  • And will take a look at simple example to implement this pattern

Bridge Design Pattern : As per the GOF definition The Bridge Pattern "Decouples an abstraction from its implementation so that the two can vary independently."

This means
  • This pattern is used to separate an abstraction from its implementation so that both can be modified independently.
  • This pattern involves an interface which acts as a bridge between the abstraction class and implementer classes.
  • By decoupling an abstraction, With Bridge pattern both types of classes can be modified without affecting to each other.

Implementation Guidelines : We need to Choose Bridge Design Pattern when
  • We want to avoid a permanent binding between an abstraction and its implementation. 
  • We need both the abstractions and their implementations should be extensible by sub classing.
  • The changes in the implementation of an abstraction should have no impact on clients that is, their code should not have to be recompiled.
  • When we  want to share an implementation among multiple objects 
  • Last but not the least when we want to hide the implementation of an abstraction completely from clients. 
Representation Diagram
bridge design pattern implementation
  • Abstraction defines the abstraction's interface and  maintains a reference to an object of type Implementor. 
  • RefinedAbstraction extends the interface defined by Abstraction.
  • Implementor defines the interface for implementation classes. This interface doesn't have to correspond exactly to Abstraction's interface. 
  • ConcreteImplementor implements the Implementer interface and defines its concrete implementation.
Before Bridge Pattern: Typical Implementation

Let assume that we need to draw different shapes such as triangle and square and fill them with different colors. Our typical approach would be to create an interface shape and implement it to Triangle and Square.

Now, let’s say we want to fill them with Blue and green colors. 

As a typical programmer we take the next step of creating different classes of triangle and square with colors. Now, if we need to fill with red and blue color we create Red Rectangle, blue.rect and red square and Blue Square…etc 

This approach works fine however it complicates the extension as things are tightly coupled here and we would want to decouple the abstraction with the implementation.

bridge design pattern implementation c#

Bridge Pattern: Implementation

Let’s see how the same diagram looks with bridge pattern implementation.
Notice that Shape has been moved to abstraction and we have refined abstraction of Triangle and Square.  Associated with this we have an Interface Color and its Implementation of concrete classes. 

This is a familiar example which is floating around the internet in various articles. However, this example simplifies to understand the bridge design pattern with the representation diagram which we discussed earlier. 

bridge design pattern implementation in .net c#

Now, let’s see how we can achieve this using another simple example

Requirement : Let’s assume that our requirement is to Process Payment of a customer who has either opted an option of Credit Card or Net banking payment during his purchase process. 

When I say purchase process, I'm sure you are familiar with a purchase on an e-commerce website where we choose the product, add it to the shopping cart and proceed with the payment. 

Typically we are provided with multiple payment option types such as Net Banking and Credit card payment and many more. For this example let’s consider we have credit card and net banking payments as the payment choices to proceed with payment

Let’s start building our code with Bridge design pattern implementation.

Step 1 : Create an interface IPaymentSystem to ProcessPayment

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BridgeDesignPattern
{
    /// <summary>
    /// Implementor Interface
    /// </summary>
    public interface IPaymentSystem
    {
        void ProcessPayment(string paymentSystem);
    }
}

Step 2 : Create Citibank as Paymentgateway and implement ProcessPayment

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BridgeDesignPattern
{
    /// <summary>
    /// ConcreteImplementor 
    /// </summary>
    public class CitiPaymentSystem : IPaymentSystem
    {
        public void ProcessPayment(string paymentSystem)
        {
            Console.WriteLine("Using CitiBank gateway for  " + paymentSystem);
        }
    }
}

Step 3 : Create IDBI as Payment gateway and implement ProcessPayment

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BridgeDesignPattern
{
    /// <summary>
    /// ConcreteImplementor
    /// </summary>
    public class IDBIPaymentSystem : IPaymentSystem
    {
        public void ProcessPayment(string paymentSystem)
        {
            Console.WriteLine("Using IDBIBank gateway for  " + paymentSystem);
        }
    }
}

Step 4 : Though we are processing payments using different payment gateways, Now a point to note here is that, for the end customer, the only that that matters is whether it’s Net banking or Credit/Debit card payment.

Which means we need to use these payment gateways and bridge them with Net Banking or Credit/Debit cards.


Let’s proceed and create those Classes of Abstraction and Refined Abstraction implementations.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BridgeDesignPattern
{
    /// <summary>
    /// Abstraction 
    /// </summary>
    public abstract class Payment
    {
        public IPaymentSystem _IPaymentSystem;
        public abstract void MakePayment();
    }
}

Step 5 : Create Refined abstraction class Card Payment and inherit the abstract class Payment

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BridgeDesignPattern
{
    /// <summary>
    /// RefinedAbstraction
    /// </summary>
    public class CardPayment : Payment
    {
        public override void MakePayment()
        {
            _IPaymentSystem.ProcessPayment("Card Payment");
        }
    }
}

Step 6 : Create Refined abstraction class Net Banking Payment and inherit the Abstract class Payment

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BridgeDesignPattern
{
    /// <summary>
    /// RefinedAbstraction
    /// </summary>
    public class NetBankingPayment : Payment
    {
        public override void MakePayment()
        {
            _IPaymentSystem.ProcessPayment("NetBanking Payment");
        }
    }
}

Step 7 : Now that we have created these refined abstractions and implemented the Abstract method for our convenience and for our representation purpose, I have moved these interfaces and classes to the corresponding folder structure of Abstraction, Refined Abstraction, Implementer and Concrete Implementer folders. 

However, it’s not mandatory to follow this structure.
bridge design pattern real time example

Step 8 : Switch to the client which is main program and implement the below code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BridgeDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Payment order = new CardPayment();
            order._IPaymentSystem = new CitiPaymentSystem();
            order.MakePayment();

            order._IPaymentSystem = new IDBIPaymentSystem();
            order.MakePayment();

            order = new NetBankingPayment();
            order._IPaymentSystem = new CitiPaymentSystem();
            order.MakePayment();

            Console.ReadKey();
        }
    }
}

Run the application and you will see the output as shown below.
Using Citibank gateway for Card Payment
Using IDBIBank gateway for Card Payment
Using Citibank gateway for NetBanking Payment

Design Patterns tutorial for beginners

No comments:

Post a Comment

If you like this website, please share with your friends on facebook and Google+ and recommend us on google using the g+1 button on the top right hand corner.