Bridge

The bridge pattern

The bridge pattern is a structural pattern, it's a little like the Adapter Pattern, but with pre-planning on the design.
You've recognised that different abstractions will have to call other abstractions and you want to be able to change each abstraction when required, so you build an abstraction, that contains another abstraction (called the implementation!):
abstract class Trance {
     // another abstract class that I can use
    protected Pontoon pontoon;

    public abstract void Bond();
}
And the Pontoon implementor:
abstract class Pontoon {
    public abstract void Scaffold();
}
Now I'm free to change the abstractions but I can always bridge to implementation.
We make a concrete implementation of Trance:
class XTrance : Trance {

    public XTrance(Pontoon pontoon) {
        this.pontoon = pontoon;
    }
    public override void Bond() {
        Console.WriteLine("XTrance bond called.");
        pontoon.Scaffold();
    }
}
I already know that inside XTrance's Bond method I need to call the Scaffold method of my implementation Pontoon. I now implement a version of Pontoon for XTrance:
class Span : Pontoon {
    private string name;

    public Span(string name) {
        this.name = name;
    }
    public override void Scaffold() {
        Console.WriteLine("Span with name:{0}, Scaffold used.", name);
    }
}
Running in a console with:
static void Main(string[] args) {
    Pontoon span = new Span("Alfred");
    Trance xTrance = new XTrance(span);

    xTrance.Bond();

    Console.ReadKey();
}
Gives the output:
XTrance bond called.
Span with name:Alfred, Scaffold used.

I also know that sometimes it needs to use a different implementor, so I build:
class Gangplank : Pontoon {
    public override void Scaffold() {
        Console.WriteLine("Gangplank Scaffold called");
    }
}
Giving it a test with:
static void Main(string[] args) {
    Pontoon span = new Span("Alfred");
    Trance xTrance = new XTrance(span);

    xTrance.Bond();

    xTrance = new XTrance(new Gangplank());
    xTrance.Bond();

    Console.ReadKey();
}
Gives the console output:
XTrance bond called.
Span with name:Alfred, Scaffold used.
XTrance bond called.
Gangplank Scaffold called

Great all working I can add implementors at will, I realise I need another abstraction but could use one of my implementors.
So I code:
class YTrance : Trance {

    public YTrance(Pontoon pontoon) {
        this.pontoon = pontoon;
    }

    public override void Bond() {
        Console.WriteLine("YTrance bond called.");
        pontoon.Scaffold();
    }
}
My console test code:
static void Main(string[] args) {
    Pontoon span = new Span("Berty");
    Trance yTrance = new YTrance(span);

    yTrance.Bond();

    Console.ReadKey();
}
My output being:
YTrance bond called.
Span with name:Berty, Scaffold used.

Pretty easy stuff but care has to be taken as one implementor could be used for many abstractions and this is no problem if it's immutable but if it's not could lead to a race condition.
Example:
static void Main(string[] args) {
    Pontoon span = new Span("Berty");
    Trance yTrance = new YTrance(span);

    yTrance.Bond();

     // same instance of Span!
    Trance yTrance = new YTrance(span);
    yTrance.Bond();

    Console.ReadKey();
}
Giving the output:
XTrance bond called.
Span with name:Alfred, Scaffold used.
YTrance bond called.
Span with name:Alfred, Scaffold used.

Summary

The bridge pattern is a useful pattern if abstractions or implementations have to be changed, as it lowers the coupling between the interacting objects but care needs to be taken not to feed a mutable implementor to a manipulating abstraction as this would be thread unsafe.

References

wiki
Design Patterns [GOF]
dofactory bridge pattern
tutorialspoint bridge pattern