---
obj: concept
---
# Bridge Pattern

## **Description:**
The Bridge Pattern is a structural design pattern that separates an object's abstraction (high-level logic) from its implementation (low-level details). It allows you to vary both the abstraction and the implementation independently, making it easier to extend and maintain complex systems. This pattern is particularly useful when you have a hierarchy of classes with multiple dimensions of variation.

**How it's Used:**
1. **Identify Abstraction and Implementation**: Identify the components of your system that have multiple dimensions of variation. This typically involves defining an abstraction (high-level logic) and one or more implementations (low-level details).
2. **Abstraction Class**: Create an abstraction class that contains a reference to an implementation object. The abstraction class defines high-level methods and delegates the implementation details to the implementation object.
3. **Implementation Interface or Abstract Class**: Define an interface or an abstract class for the implementation, which will be implemented by concrete implementation classes.
4. **Concrete Implementation Classes**: Create concrete implementation classes that implement the interface or extend the abstract class defined for the implementation. These classes contain the low-level implementation details.
5. **Client Code**: In your client code, use the abstraction class to interact with the high-level logic while providing or selecting the specific implementation at runtime.

## **Example:**
Consider a drawing application where you have different shapes (e.g., circles, rectangles) that can be drawn using different rendering techniques (e.g., vector graphics, raster graphics). Here's how the Bridge Pattern can be applied:

- **Abstraction Class**: Create an abstraction class `Shape` that contains a reference to an implementation object `Renderer`.
```java
public abstract class Shape {
    protected Renderer renderer;

    public Shape(Renderer renderer) {
        this.renderer = renderer;
    }

    public abstract void draw();
}
```

- **Implementation Interface**: Define an interface `Renderer` for the rendering implementation.
```java
public interface Renderer {
    void render();
}
```

- **Concrete Implementation Classes**: Create concrete implementation classes for different rendering techniques, such as `VectorRenderer` and `RasterRenderer`.
```java
public class VectorRenderer implements Renderer {
    @Override
    public void render() {
        System.out.println("Rendering as vector graphics.");
    }
}

public class RasterRenderer implements Renderer {
    @Override
    public void render() {
        System.out.println("Rendering as raster graphics.");
    }
}
```

- **Concrete Abstraction Classes**: Create concrete abstraction classes for different shapes, such as `Circle` and `Rectangle`, that extend the `Shape` class and provide specific implementations for the `draw` method.
```java
public class Circle extends Shape {
    private int radius;

    public Circle(Renderer renderer, int radius) {
        super(renderer);
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Drawing a circle with radius " + radius);
        renderer.render();
    }
}

public class Rectangle extends Shape {
    private int width;
    private int height;

    public Rectangle(Renderer renderer, int width, int height) {
        super(renderer);
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing a rectangle with width " + width + " and height " + height);
        renderer.render();
    }
}
```

- **Client Code**: In your application, use the abstraction classes to create shapes and specify the rendering technique at runtime.
```java
public class Client {
    public static void main(String[] args) {
        Renderer vectorRenderer = new VectorRenderer();
        Renderer rasterRenderer = new RasterRenderer();

        Shape circle = new Circle(vectorRenderer, 5);
        Shape rectangle = new Rectangle(rasterRenderer, 10, 20);

        circle.draw();
        rectangle.draw();
    }
}
```

By using the Bridge Pattern, you can vary the shapes and rendering techniques independently, making it easier to add new shapes or rendering methods without affecting existing code. This pattern promotes flexibility and maintainability in complex systems with multiple dimensions of variation.