BlackWaspTM
Design Patterns
.NET 1.1+

Bridge Design Pattern (2)

The bridge pattern is a design pattern that separates the abstract elements of a class from its technical implementation. This provides a cleaner implementation of real-world objects and allows the implementation details to be changed easily.

Implementing the Bridge Pattern

Bridge Design Pattern UML

The UML class diagram above describes an implementation of the bridge design pattern. The items in the diagram are described below:

  • Abstraction. This class contains members that define an abstract business object and its functionality. It also acts as the base class for other, more refined, abstractions. Objects of this type hold a reference to the particular implementation that they are using for platform-specific functions. No other member of the class deals with implementation details.
  • RefinedAbstraction. Many refined abstractions may inherit from the Abstraction class. Each provides a more specific variation upon the abstraction but still contains no implementation details other that those in the Implementation object reference that they hold.
  • ImplementationBase. This abstract class is the base class for all classes that provide implementation details for the associated abstractions. The class provides a fixed interface that can be utilised by the abstractions. The interface need not be similar to that of the abstraction. This class may be implemented as an interface if it provides no real functionality for its subclasses.
  • ConcreteImplementation. The ConcreteImplementation class inherits form the ImplementationBase class. There may be multiple concrete implementation classes, each providing the same interface but providing platform-specific functionality.

The following shows the basic code of the bridge design pattern implemented using C#. For brevity, the Abstraction class' Implementer property is declared using C# 3.0 automatically implemented property syntax. For earlier versions of the .NET framework, define the property in full and use the protected scope for the backing variable so that it is also available to refined abstractions.

public class Abstraction
{
    public ImplementationBase Implementer { get; set; }

    public virtual void Operation()
    {
        Console.WriteLine("ImplementationBase:Operation()");
        Implementer.OperationImplementation();
    }
}


public class RefinedAbstraction : Abstraction
{
    public override void Operation()
    {
        Console.WriteLine("RefinedAbstraction:Operation()");
        Implementer.OperationImplementation();
    }
}


public abstract class ImplementationBase
{
    public abstract void OperationImplementation();
}


public class ConcreteImplementation1 : ImplementationBase
{
    public override void OperationImplementation()
    {
        Console.WriteLine("ConcreteImplementation1:OperationImplementation()");
    }
}


public class ConcreteImplementation2 : ImplementationBase
{
    public override void OperationImplementation()
    {
        Console.WriteLine("ConcreteImplementation2:OperationImplementation()");
    }
}
8 April 2009