Description
The bridge pattern decouples an abstraction from its implementation so that the two can vary independently. It imposes flexibility by providing contracts instead of concrete classes.
Imagine you have a function that renders a video. Depending on the video file type you will provide multiple plugins options. These plugins all derive from a base class and that base class is the “Implementor”.
Abstraction
Maintains a reference to an object of type Implementor.
RefinedAbstraction
An extended class inheriting Abstraction.
Implementor
Defines the interface for the concrete Implementor. It doesn’t have to be related to the Abstraction. In general the abstraction has a relation of “has” with the Implementor and it defines high level instructions on it.
Concrete Implementor
Implements the Implementor interface and defines its concrete implementation.
At a first look it seems that this design pattern doesn’t bring anything new. You have a class (The refined abstraction) which has a property and that property is nothing more then the implementor.
However the code works with abstractions (e.g. Color, Shape) and not concrete classes and this provides more flexibility and scalability to the code. And on some level it resembles with the flyweight pattern, one type of color is created once and the reference to that color is passed to all objects with that color.
And this reminds us to the first quote we learn in OOP (well..in this case to an abstract class)
Program to Interface, not Implementation
Implementor
// An abstract class that binds concrete implementors to provide a color public abstract class Color { public abstract int Red { get; } public abstract int Green { get; } public abstract int Blue { get; } //other methods or properties can be defined }
Concrete Implementor
//Concrete implementor public class ColorRed : Color { public override int Red => 255; public override int Green => 0; public override int Blue => 0; } public class ColorYellow : Color { public override int Red => 255; public override int Green => 255; public override int Blue => 0; }
Abstraction
//The abstraction class public abstract class Shape { //The implementor protected Color Color; public Shape(Color color) { this.Color = color; } public string GetColorString() { return string.Format("The color is R={0} G={1} B={2}",Color.Red, Color.Green, Color.Blue); } }
Refined abstraction
//The Refined abstraction public class Square : Shape { public Square(Color color) : base(color) { } public override string ToString() { return string.Format("The color for the square is {0}" , this.GetColorString()); } }