Bridge

Decouples an abstraction from its implementation so that both can evolve independently.

Context

You have a hierarchy of shapes (circle, square) and a hierarchy of renderers (SVG, Canvas). If you cross them with inheritance, you get a combinatorial explosion: SvgCircle, CanvasCircle, SvgSquare...

Problem
  • You couple two hierarchies that change for different reasons.
  • Any new variant multiplies the number of classes.
Solution

Separate abstraction (the stable hierarchy) from implementation (the interchangeable hierarchy) and connect them through composition.

#Example in C#

public interface IRenderer { void DrawCircle(double x, double y, double r); }

public class SvgRenderer    : IRenderer { public void DrawCircle(double x,double y,double r) {/* svg */} }
public class CanvasRenderer : IRenderer { public void DrawCircle(double x,double y,double r) {/* canvas */} }

public abstract class Shape
{
    protected readonly IRenderer Renderer;
    protected Shape(IRenderer r) => Renderer = r;
    public abstract void Draw();
}

public class Circle : Shape
{
    private readonly double _x, _y, _r;
    public Circle(IRenderer r, double x, double y, double radius) : base(r)
        => (_x, _y, _r) = (x, y, radius);
    public override void Draw() => Renderer.DrawCircle(_x, _y, _r);
}
When NOT to use it

When you only have one implementation or don't expect new variants.

Tradeoffs
Pro Con
Avoids combinatorial explosion Higher initial complexity
Allows changing implementation at runtime More indirection

#structural #gof