Рассмотрение ядра программной системы я решил начать именно с этого паттерна, потому что в своё время его слишком наукообразное определение меня повергло в полнейший ступор. Приведу его дословно.
Мост — это структурный паттерн проектирования, который разделяет один или несколько классов на две отдельные иерархии — абстракцию и реализацию, позволяя изменять их независимо друг от друга.
Как ни странно, столкнувшись с одной задачей и увидев по-своему способ её решения, я интуитивно понял, что это и есть тот самый Мост. И когда покопался в справочных материалах повнимательнее, окончательно убедился в своей правоте, ознакомившись с примерами.
А теперь я хочу пересказать это своими словами, при чём сначала не на техническом примере, а на жизненном.
Допустим, у нас есть большая корпорация с разнообразным управленческим составом: от линейных руководителей до топ-менеджеров. И так же есть технический персонал: слесари, водители, электрики. Ясно, что когда возникает необходимость что-то починить или подогнать куда-то машину, топ-менеджер лично этого делать не будет. Он занят своими прямыми обязанностями, а задачи, которые касаются техники нужно делегировать соответствующим специалистам.
Теперь пример из программы
Меня в своё время сбило с толку слово "абстракция", и я подумал, что речь идёт об интерфейсах, или, по крайней мере, абстрактных классах. И я плохо понимал, как отделить от них реализацию.
Так вот, братья-программисты, не ведитесь на это (и сёстры тоже)! В обеих иерархиях здесь может быть что угодно: интерфейсы, абстрактные классы, классы с реализацией - речь вообще не об этом. Просто есть основная иерархия классов, объектам которых нужно вызывать один из нескольких вариантов функционала, инкапсулированного в классах, которые, в свою очередь, тоже объединены в иерархию. Мы не знаем, какой именно класс реализации функционала понадобится, поэтому в базовый класс первой иерархии вставляем ссылку на базовый класс второй иерархии.
Это и есть мост. Теперь расскажу, какую задачу я решал с помощью этого паттерна и почему её нельзя было решить простым наследованием.
На диаграмме я постарался выразить суть дела с помощью цветов. Серым цветом показаны "главы" двух иерархий: базовый класс всех парсеров и базовый класс всех БукКрейтеров - классов, отвечающих за создание выходных файлов.
Желтым цветом показаны все классы, связанные с Опенкартом. Можно заметить, что базовые классы для парсинга в базу Опенкарта с веб-страниц и Excel-документов и класс создания документа импорта/экспорта (вверху слева) действительно похожи на островки, разделённые синей рекой. Синем цветом показаны классы, которые не имеют ни какого отношения к Опенкарту и не могут содержать код, связанный с этой CMS.
Для устранения этой проблемы в базовый класс парсера добавлена ссылка на крейтер (показанная на диаграмме красной стрелкой), которая инициируется в конструкторе производных классов (см. скриншот).
Если возвращаться к примеру, который я привёл до этого, с руководителями и техническим персоналом, роль моста здесь, может выполнять директор по материальному обеспечению, который отслеживает всё, что касается техники и принимает решение, какому специалисту поручить ту или иную работу.