Ответ
Bridge — это структурный шаблон проектирования, который разделяет абстракцию (интерфейс или высокоуровневую логику) и её реализацию (низкоуровневые детали) в отдельные иерархии классов. Это позволяет изменять их независимо друг от друга, используя композицию вместо наследования.
Проблема, которую решает Мост: Избежать «разбухания» класса из-за комбинаторного взрыва подклассов (например, CircleRed, CircleBlue, SquareRed, SquareBlue).
Ключевые компоненты:
- Abstraction (Абстракция): Определяет высокоуровневый интерфейс и содержит ссылку на объект
Implementor. - RefinedAbstraction (Уточнённая абстракция): Расширяет интерфейс, определённый
Abstraction. - Implementor (Реализатор): Определяет интерфейс для низкоуровневых операций.
- ConcreteImplementor (Конкретный реализатор): Содержит конкретную реализацию интерфейса
Implementor.
Пример: Фигуры и цвета
// 1. Иерархия Реализации (Цвета)
interface Color {
String fill();
}
class Red implements Color {
@Override
public String fill() { return "красным"; }
}
class Blue implements Color {
@Override
public String fill() { return "синим"; }
}
// 2. Иерархия Абстракции (Фигуры)
abstract class Shape {
protected Color color; // Композиция! Мост между абстракцией и реализацией
public Shape(Color color) { this.color = color; }
abstract String draw();
}
class Circle extends Shape {
public Circle(Color color) { super(color); }
@Override
public String draw() {
return "Рисую круг, залитый " + color.fill();
}
}
class Square extends Shape {
public Square(Color color) { super(color); }
@Override
public String draw() {
return "Рисую квадрат, залитый " + color.fill();
}
}
// Использование
Color red = new Red();
Shape redCircle = new Circle(red);
System.out.println(redCircle.draw()); // Рисую круг, залитый красным
Shape blueSquare = new Square(new Blue());
System.out.println(blueSquare.draw()); // Рисую квадрат, залитый синим
Преимущества:
- Разделение ответственности: Абстракция и реализация развиваются независимо.
- Принцип открытости/закрытости: Можно добавлять новые абстракции и реализации, не меняя существующий код.
- Сокрытие деталей реализации от клиентского кода.
Применение: Драйверы устройств, GUI-фреймворки (отделение платформо-зависимой части), API, работающие с разными типами баз данных.
Ответ 18+ 🔞
Ну вот, сидишь ты, такой весь из себя архитектор, пишешь свой код. Всё вроде красиво: есть у тебя Circle, есть Square. И тут бац — тебе говорят: «А сделай-ка их ещё и красными, и синими». Ну, думаешь, ерунда, щас наследуемся: RedCircle, BlueCircle, RedSquare, BlueSquare. А потом приходят и говорят: «А ещё есть прозрачность, а ещё есть градиент, а ещё есть, блядь, текстура „под старый дуб“». И вот ты уже сидишь с сотней классов, у которых в названии вся твоя еб*ная жизнь не помещается. Это, дружок, и есть тот самый комбинаторный взрыв, от которого волосы дыбом и терпения — ноль, ебать.
Так вот, чтобы не сойти с ума, умные дядьки придумали Мост (Bridge). Суть проста, как три копейки: ты берёшь и разводишь в разные стороны то, что ты делаешь (абстракция — например, фигура), и то, как ты это делаешь (реализация — например, цвет).
Вот смотри, как это выглядит в деле, без всей этой академической ху*ты:
// 1. Это наша "реализация" — то, КАК мы будем заливать цветом. Отдельная иерархия, живёт сама по себе.
interface Color {
String applyColor();
}
class FuckingRed implements Color {
@Override
public String applyColor() { return "яростно-красным"; }
}
class SadBlue implements Color {
@Override
public String applyColor() { return "тоскливо-синим"; }
}
// 2. А это наша "абстракция" — то, ЧТО мы рисуем. Она НЕ наследует цвет, а содержит ссылку на него. Это и есть МОСТ!
abstract class Shape {
protected Color color; // Вот он, сука, мост! Композиция, а не наследование!
public Shape(Color color) { this.color = color; } // Подсовываем реализацию снаружи
abstract String draw();
}
// 3. Конкретные фигуры. Им похуй, какой именно цвет им пришлют.
class Circle extends Shape {
public Circle(Color color) { super(color); }
@Override
public String draw() {
return "Рисую круг и заливаю его " + color.applyColor(); // Просто пользуемся мостом
}
}
class Square extends Shape {
public Square(Color color) { super(color); }
@Override
public String draw() {
return "Вывожу квадрат, залитый " + color.applyColor();
}
}
// 4. А теперь, ёпта, магия!
public class Main {
public static void main(String[] args) {
Color angryColor = new FuckingRed();
Shape circle = new Circle(angryColor);
System.out.println(circle.draw()); // Рисую круг и заливаю его яростно-красным
// Или вот так, в одну строку, не заморачиваясь
Shape square = new Square(new SadBlue());
System.out.println(square.draw()); // Вывожу квадрат, залитый тоскливо-синим
}
}
В чём, блядь, фокус?
- Фигуры (абстракция) и Цвета (реализация) теперь — как два независимых модуля. Хочешь добавить новый цвет
PsychodelicRainbow? Пожалуйста! Пишешь один класс, и он автоматически будет работать со всеми существующими фигурами. Ни одного существующего класса фигур трогать не надо! Это и есть принцип открытости/закрытости в действии, ебать его в сраку. - Клиентский код (тот, который в
main) теперь не привязан к конкретным комбинациям. Он просто собирает нужную ему связку из абстракции и реализации, как из конструктора «Лего».
Где этот мост полезен? Да везде, где есть эта проклятая «платформенная зависимость»:
- Драйверы баз данных (одна абстракция — запрос, много реализаций: для MySQL, PostgreSQL, Oracle).
- GUI-фреймворки (окно — это абстракция, а отрисовка кнопок под Windows, MacOS или Linux — это реализация).
- Разные API для отправки уведомлений (SMS, Email, Push) — логика одна, а каналы разные.
Короче, Мост — это когда ты перестаёшь плодить сущности как сумасшедший и начинаешь грамотно разделять матчасть. Чисто, гибко, и голова не болит.