Какую проблему решает паттерн проектирования Мост (Bridge) и как он это делает?

Ответ

Паттерн Мост (Bridge) решает проблему комбинаторного взрыва подклассов, когда абстракция и её реализация должны изменяться независимо. Он разделяет их на две отдельные иерархии, связывая их композицией, а не наследованием.

Проблема без Моста: Shape (Фигура) может быть Circle или Square. Каждая фигура может быть отрисована в Red, Blue или Green. Это приводит к классам RedCircle, BlueCircle, RedSquare и т.д.

Решение с Мостом:

// 1. Иерархия Реализации (не зависит от абстракций)
interface Renderer {
    String renderShape();
}

class VectorRenderer implements Renderer {
    public String renderShape() {
        return "as vector graphics";
    }
}

class RasterRenderer implements Renderer {
    public String renderShape() {
        return "as pixels";
    }
}

// 2. Иерархия Абстракции (содержит ссылку на реализацию)
abstract class Shape {
    protected Renderer renderer; // Мост — композиция

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

    public abstract String draw();
}

class Circle extends Shape {
    public Circle(Renderer renderer) {
        super(renderer);
    }

    public String draw() {
        return "Drawing Circle " + renderer.renderShape();
    }
}

// 3. Использование: Абстракция и реализация комбинируются динамически
Shape vectorCircle = new Circle(new VectorRenderer());
System.out.println(vectorCircle.draw()); // "Drawing Circle as vector graphics"

Shape rasterCircle = new Circle(new RasterRenderer());
System.out.println(rasterCircle.draw()); // "Drawing Circle as pixels"

Итог: Добавление новой фигуры или нового типа отрисовки требует создания только одного нового класса, а не серии комбинаций.

Ответ 18+ 🔞

Да ты посмотри на эту дичь, блядь! Вот сидишь ты такой, пишешь свой код, и тут бац — тебе нужно фигуры рисовать. Круги там, квадраты, треугольники всякие. И рисовать их надо по-разному: вектор, растр, может, ещё в ASCII-арт, ёпта.

И что делает обычный, недалёкий программист? Правильно, начинает плодить классы как сумасшедший! RedCircle, BlueCircle, RedSquare, GreenTriangle... Да их же, блядь, овердохуища получится! Это ж комбинаторный взрыв, пиздец просто. Добавил новый цвет — и пошёл по всем фигурам плодить подклассы. Добавил новую фигуру — и пошёл по всем рендерерам. Задолбаешься, как та собака Муму.

А паттерн Мост говорит: "Да похуй, чувак! Давай разделим эту хуйню на две независимые ветки". Одна ветка — это что мы рисуем (абстракция). Другая — как мы это рисуем (реализация). И свяжем их не через наследование, а через композицию, то есть просто вставим одну штуку в другую, как хуй в пальто.

Смотри, как это выглядит без мозгоёбства:

// 1. Это наша "реализация" — то, КАК рисовать. Ей похуй на фигуры.
interface Renderer {
    String renderShape();
}

class VectorRenderer implements Renderer {
    public String renderShape() {
        return "as vector graphics"; // Чистая математика, сука, линии и кривые!
    }
}

class RasterRenderer implements Renderer {
    public String renderShape() {
        return "as pixels"; // А это уже для плебеев, пиксели квадратные
    }
}

// 2. А это наша "абстракция" — то, ЧТО рисуем. Ей похуй на способы.
abstract class Shape {
    protected Renderer renderer; // Вот он, самый сок! Мост, блядь. Держим ссылку на "как".

    public Shape(Renderer renderer) {
        this.renderer = renderer; // Подсовываем реализацию снаружи. Гибко, а?
    }

    public abstract String draw(); // А вот тут уже используем эту реализацию
}

class Circle extends Shape {
    public Circle(Renderer renderer) {
        super(renderer);
    }

    public String draw() {
        // Берём своё "что" (Круг) и комбинируем с "как" (рендерером)
        return "Drawing Circle " + renderer.renderShape();
    }
}

// 3. А теперь, внимание, магия!
public class Main {
    public static void main(String[] args) {
        // Хочу круг, но нарисованный вектором!
        Shape vectorCircle = new Circle(new VectorRenderer());
        System.out.println(vectorCircle.draw()); // Drawing Circle as vector graphics

        // Хочу тот же круг, но в пикселях!
        Shape rasterCircle = new Circle(new RasterRenderer());
        System.out.println(rasterCircle.draw()); // Drawing Circle as pixels
    }
}

Итог-то какой, спросишь? А такой, блядь: теперь если тебе понадобится новый способ рисования, например, HologramRenderer, ты просто создашь один класс, реализующий Renderer. И ВСЕ существующие фигуры (круг, квадрат, твой член) сразу смогут им пользоваться! И наоборот — добавил новую фигуру Pentagon, и она сразу работает со всеми рендерерами. Никакого комбинаторного ада. Красота, ёпта! Чистая архитектура, а не пиздопроебибна какая-то.