В чём суть паттерна проектирования «Мост» (Bridge)?

«В чём суть паттерна проектирования «Мост» (Bridge)?» — вопрос из категории Паттерны, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Мост (Bridge) — это структурный паттерн проектирования, который разделяет один или несколько классов на две отдельные иерархии — абстракцию и реализацию, позволяя изменять их независимо друг от друга.

Проблема: Наследование жёстко связывает реализацию с абстракцией, что приводит к "разрастанию" классов (например, CircleBlue, CircleRed, SquareBlue, SquareRed).

Решение Bridge: Заменить наследование композицией, вынесли вариативную часть («реализацию») в отдельную иерархию.

Ключевые компоненты:

  1. Абстракция (Abstraction): Определяет интерфейс высокоуровневой логики и содержит ссылку на объект Реализации.
  2. Расширенная абстракция (Refined Abstraction): Вариации или расширения базовой абстракции.
  3. Реализация (Implementor): Интерфейс для всех конкретных реализаций.
  4. Конкретная реализация (Concrete Implementor): Конкретные классы, реализующие интерфейс Implementor.

Пример на Java (Фигуры и способы их рисования):

// 1. Implementor: Интерфейс реализации (инструмент рисования)
interface Renderer {
    String renderShape(String shapeName);
}

// 2. Concrete Implementor A
class VectorRenderer implements Renderer {
    public String renderShape(String shapeName) {
        return "Drawing " + shapeName + " as vector graphics.";
    }
}

// 3. Concrete Implementor B
class RasterRenderer implements Renderer {
    public String renderShape(String shapeName) {
        return "Rasterizing " + shapeName + " to pixels.";
    }
}

// 4. Abstraction: Абстракция фигуры
abstract class Shape {
    protected Renderer renderer; // Мост!

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

    public abstract String draw();
}

// 5. Refined Abstraction
class Circle extends Shape {
    private String name;

    public Circle(Renderer renderer, String name) {
        super(renderer);
        this.name = name;
    }

    @Override
    public String draw() {
        return renderer.renderShape("Circle: " + name); // Делегирование реализации
    }
}

// Клиентский код
public class BridgeDemo {
    public static void main(String[] args) {
        Shape vectorCircle = new Circle(new VectorRenderer(), "Small Circle");
        Shape rasterCircle = new Circle(new RasterRenderer(), "Large Circle");

        System.out.println(vectorCircle.draw()); // Drawing Circle: Small Circle as vector graphics.
        System.out.println(rasterCircle.draw());  // Rasterizing Circle: Large Circle to pixels.
    }
}

Преимущества:

  • Разделение ответственности: Абстракция и реализация развиваются независимо.
  • Принцип открытости/закрытости: Можно вводить новые абстракции и реализации, не изменяя существующий код.
  • Принцип единственной ответственности: Абстракция занимается высокоуровневой логикой, реализация — деталями платформы.

Применение: Часто используется в драйверах, графических библиотеках, когда нужно поддерживать несколько типов платформ или API.