Шаблон Bridge дополнительные штрихи

    Обсуждение многострадального шаблона Bridge на хабре, выявило много интересных мнений и заблуждений. Попробуем разобраться, реанимировать данный шаблон в глазах тех кто борется с формулировками оригинального каталога GoF, а интересующимся темой шаблонов показать несколько дополнительных штрихов.


    Кратко о шаблонах GoF (Gang of Four – «банда четырех»)



    «Мы не наделены даром предвидения, поэтому те, кто приписывает «банде четырех» экстраординарные способности, будут поражены хаотичностью нашего процесса разработки.»
    Джон Влиссидес

    «Когда мы писали нашу книгу, мы действительно пытались кое-что скрыть, Нам хотелось избежать разговоров о том, что один шаблон является специализацией другого или один шаблон содержится в другом в качестве его компонента. Мы не хотели отвлекаться, и решили говорить только о шаблонах. Отчасти поэтому мы не описали в качестве самостоятельного шаблона «абстрактный класс», поскольку он содержится в большинстве шаблонов. Я думаю, это было оправданное решение при создании первого каталога шаблонов, но сейчас ситуация изменилась. Люди хотят знать о связях между шаблонами, и мы должны рассказать им об этом.»
    Ральф Джонсон

    «Разработанные GoF шаблоны проектирования учитывают только аспекты микроархитектуры. Необходимо правильно выбрать макроархитектуру: разбиение на уровни, распределение, изоляцию функций..., а также наноархитектуру: инкапсуляцию, принцип подстановки Лисков (Barbara Liskov). Возможно, кое-где удастся использовать некий шаблон проектирования, во всяком случае, весьма маловероятно, что такой шаблон уже разработан и описан в какой-нибудь книге.»
    Ричард Хелм

    Шаблоны GoF построены на двух базовых принципах
    1. Найдите точки изменений и инкапсулируйте их.
    2. Композиция объектов во время выполнения предпочтительнее наследования.
    Критерии для включения шаблона в каталог
    • Воспроизводимость приема как минимум в 3-х независимых реализациях. По возможности независимо от языка программирования.
    • Согласие группы с именем (метафорой) и базовой структурой шаблона.


    Шаблон Bridge («Мост»)



    Тип: структурный
    Уровень: компонент
    Другое название: Handle/Body («Описание/тело»)
    Время применения: момент проектирования.

    Назначение
    Разделение сложного компонента на две независимые, но взаимосвязанные иерархические структуры: функциональную абстракцию и внутреннюю реализацию.
    Это облегчает изменение любого аспекта компонента.

    Демонстрация

    Рассмотрим идеи лежащие в основе данного шаблона на примере моделирования компонента под названием «Автомобиль». Практическая ценность не будет самоцелью.
    Шаг 1. Иерархия функциональных возможностей (первый уровень), в данном случае это будут укрупненные виды автомобилей.


    Шаг 2. Пространство реализаций будет отражать варианты представления автомобиля в недрах компании производителя. Обратите внимание на взрывное увеличение статических связей в модели и соответственно кол-во классов подлежащих разработке при использовании наследования. Но в момент выполнения сложность модели линейная.




    Шаг 3. Разделение иерархий, откладывание связывания до момента выполнения. Сравните со схемотехническим элементом «многопозиционный переключатель» или «мультиплексор».


    Шаг 4. «Классическое» представление шаблона с учетом указанных особенностей.


    Сравнение с наследованием

    Варианты функциональности:__2…..3....3…4…...4….5
    Варианты реализации:________2…..2….3….3…...4….4
    Классы (наследование):______ 4…..6….9…12...16...20
    Классы (шаблон Bridge):______ 4....5….6…7…...8…..9

    Архитектура шаблона Bridge позволяет выполнять мультиплексирование разных вариантов внешнего представления и внутренней реализации компонента. Термин «мультиплексирование» означает возможность ассоциации в любой комбинации внешних и внутренних элементов, что обеспечивает увеличение диапазона возможных вариаций компонента.
    Разделение компонента на две отдельные концепции, кроме того, способствует облегчению понимания назначения компонента и его сопровождения. Это объясняется тем, что каждая ветвь наследования выстраивается на основании одной концепции — либо абстракции, либо реализации.

    Важные моменты


    Границы: Функции и реализация это тесно связанные иерархии, находящиеся на одном концептуальном уровне, отражающие особенность структуры одного компонента. Обратите внимание, что реализация находится в «private/protected» части компонента и отражает точки вариации функциональной концепции.
    Пример: GUI в Java. Public находится в java.awt.*. Private во внутренних пакетах sun.*. Это обеспечивает защиту важного инварианта т.к нет никакого смысла использовать например на Win реализацию под Mac, и тем более позволять внешнему (недоверенному) коду подменять реализацию.

    Главная иерархия: Функциональная иерархия является главной, она знает о вариации и использует ее (однонаправленная ассоциация). Иерархия реализации подчинена потребностям требуемых функций. Именно поэтому в GoF получается, что метод DrawRectangle() находится на функциональном уровне, а DrawLine() на уровне платформенных реализаций.
    При двунаправленной ассоциации у нас получается уже не «мост», а «посредник» по GoF.

    Место среди структурных шаблонов: Классическая формулировка говорит о равнозначимости изменения обоих иерархий. Однако один из «бандитов» Джон Влиссидес приводится следующий список точек вариации.
    ADAPTER — интерфейс объекта;
    BRIDGE — реализацию объекта;
    COMPOSIТЕ — структуру и состав объекта;
    DECORATOR — обязанности объекта без порождения подкласса;
    FACADE — интерфейс подсистемы;
    FLYWEIGHT — накладные расходы на хранение объектов;
    PROXY — способ доступа к объекту и/или его местоположение.

    Связь с другими шаблонами: Если вы пытаетесь перейти к «мосту» в существующей модели, то в 99% случаев вы либо агрегируете/адаптируете независимые сущности либо используете посредника/стратегию для инкапсуляции изменений, просто не забывайте что исходный шаблон это прием времени проектирования (иногда рефакторинга), такой начальный шаг, но как только ваша «реализация» выйдет из «private» зоны и заживет самостоятельно это уже не «мост». Связь между уровнями, инверсия зависимостей что угодно только не «мост» в смысле GoF.
    «Мост» нужно «конфигурировать» в момент выполнения, не забывайте возможно любое сочетание Абстракция — Реализация. Логика «конфигурирования» и соблюдения инвариантов либо спрятана в компоненте либо отдается компоненту более высокого уровня (в сложных случаях может быть Абстрактная фабрика, контейнер зависимостей и т.п).
    Такие варианты, как разделение реализации между объектами в момент выполнения, использование нескольких реализаций одновременно. Описаны у GoF и их можно считать экзотическими случаями в которых «мост» контекст для применения другого шаблона.

    Определите для вашего компонента: что означает концепция равенства сущностей применительно к шаблону Bridge. Нужно ли сравнивать только абстракции либо только реализации объектов, или же нужно рассматривать их в совокупности?

    Проблема качества модели: состоит в том, что нередко разработка реализации шаблона выполняется на основе одной или двух возможных вариаций. Опасность заключается в том, что при последующем развитии шаблона выясняется, что некоторые из элементов, считавшихся базовыми, на самом деле представляют собой конкретные вариации, базирующиеся на абстракции и (или) реализации. Данный момент несколько сумбурно был изложен в статье пользователя tac ссылка. Но здесь важно помнить, что шаблоны не определяют качество модели предметной области, глубина и адекватность модели существенно зависит от первичных задач приложения, квалификации проектировщика и мнения экспертов в соответствующей области.
    Эмпирический (механический) критерий — если здесь и сейчас (в момент проектирования) вам действительно нужно (Варианты функциональности + Варианты реализации) > 6 т.е соотношение уровня 3:3, 3:4 и выше, то
    — разбивайте иерархии
    — какое соотношение объема кода получилось 80%:20%, 50%:50%, 20%-80%?
    — подумайте не распалась ли ваша исходная концепция на независимые сущности?

    Проблема исходной метафоры: строительная метафора + невнятная формулировка в каталоге приводят к тому, что любую горизонтальную стрелочку между двумя независимыми иерархиями объявляют «мостом». Метафора «мультиплексор» лучше отражает базовую технику реализации, а ограничение уровнем одного компонента проводит понятную логическую границу с другими шаблонами.
    Надеюсь изложенные «дополнительные штрихи» позволили четче показать суть шаблона.

    Список литературы

    Э. Гамма, Р. Хелм, Р. Джонсон, Д. Влиссидес — Приемы объектно-ориентированного проектирования. Паттерны проектирования. Каталог шаблонов GoF.
    Дж. Влиссидес — Применение шаблонов проектирования. Дополнительные штрихи. Здесь описаны шаблоны, не вошедшие в основной каталог Pull/Push, Multicast…и просто интересные зарисовки творческих мук «банды».
    А. Шаллоуей, Дж. Тротт — Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию. Рассуждения о невнятности формулировки «моста» и поиск контекста применения. Также хорошие рассуждения о сочетании/применении шаблонов.
    С.Стелтинг, О.Маассен — Применение шаблонов JAVA. Четкое позиционирование «моста» как шаблона уровня компонента. Введение метафоры телефонный коммутатор.
    Поделиться публикацией

    Комментарии 27

      +5
      Всё таки я хочу разобраться правильно ли я понимаю «мост».

      Есть абстрактный класс EntityRepository, от него наследуются UserRepository, PostRepository, CommentRepository, возможно реализующие специфичные для конкретных Entity методы (например, CommentRepository::getCommentsByAuthor).

      Есть абстрактный класс AbstractEntityStorage, от него наследуются FileEntityStorage, MySqlEntityStorage, CouchDbEntityStorage, реализующие одни и те же методы сильно разными способами.

      В момент инициализации (то есть в рантайме) *Repository создаётся нужный (из конфига) *EntityStorage и сохраняется в приватном/защищенном свойстве репозитория. В дальнейшем методы репозитория вызывают методы хранилища, не догадываясь какая конкретная функциональность за ними скрывается.

      Это мост?
        +2
        Это «мост» если:

        — все методы EntityStorage подчинены потребностям EntityRepository
        — EntityStorage используется только EntityRepository
        — Любой Entity требует для полноценного функционирования EntityStorage
        — EntityStorage ничего не знает о EntityRepository, например передача Entity в методы EntityStorage приводит к переходу от однонаправленной зависимости к двунаправленной, что здорово ограничивает возможности «независимого» развития.

        В вашем случае достаточно высокоуровневая конструкция и реальным шаблоном является Хранилище(Repository) из практик DDD.
        Посмотрите позиционирование GoF по мнению Ричарда Хелми в начале статьи.
        С GoF шаблон Repository пересекается лишь на уровне базового принципа «инкапсуляция точек вариации» т.е в данном случае вариация в способе сохранения в Storage.
        При всей простоте принципа «вариация» он фундаментален и масштабируем до уровня высокоуровневой архитектуры.
        В этом единство шаблонов GoF, когда разработчик слышит «хочу менять алгоритмы» он говорит «Стратегия», слышит «хочу менять реализацию» говорит «мост», слышит «хочу менять внутренне состояние объекта» говорит «состояние», но фокус в том, что получившаяся структурная диаграмма и базовый принцип неотличимы. Различаются мотивации. Такая вот педагогический прием ориентация на «рефлекс» разработчика, «триггер» который щелкает при ключевых словах/метафорах. Даже если вся базовые принципы сведены к двум перечисленным в начале статьи.
          0
          А реализация != алгоритм?

          FileEntityStorage, MySqlEntityStorage, CouchDbEntityStorage это не мост. Это адаптеры.
            0
            Вообще все пункты «Это «мост» если» выдуманы.

            Это «мост» если:
            — код еще не написан, либо написана заглушка
            — вы сами определяется интерфейс для будущих реализаций
            — можно было бы использовать наследование, но composition всегда лучше для не 'is a'.
            — в мосте реализован паттерн strategy для возможность поменять реализацию

            Это «адаптер» если:
            — у вас уже есть старый код
            — и вы хотите адаптировать его интерфейс под свои нужды
              0
              «вы сами определяется интерфейс для будущих реализаций»

              об этом и идет речь когда выясняем кто-кому подчинен.

              «реализация != алгоритм?»

              В ООП да, под реализацией объекта понимается сочетание Данные + Алгоритмы обработки. Алгоритм по по себе не имеет состояния кроме тех данных, что он получил как входные.
                0
                В этом разница между шалонами Стратегия и Состояние, в первом мы акцентируемся на алгоритме обработки (контекст и данные передаются как входные) во втором на полном состоянии объекта.
                  0
                  «В ООП да, под реализацией объекта понимается сочетание Данные + Алгоритмы обработки»
                  Не согласен. Говорят что класс реализует интерфейс, а значит класс — это реализация интерфейса.

                  Но да, я ошибся, это не одно и то же. Алгоритм это из области решаемой проблемы, а реализация алгоритма это уже сам класс.
                0
                Адаптерами их, по-моему, сложно назвать. Они изменяют уровень абстракции. Адаптеры, по-моему, за пределы уровня не выходят.
            –2
            мост
              0
              Мне понравились примеры с этого сайта.

              Проблема: есть пересечение множеств сущностей. В данном случае, Thread Scheduler'ов и операционных систем.
              image

              Добавлять поддержку новых операционных систем неудобно. Рефакторим, выделяя отдельную иерархию операционных систем:

              image

              Я правильно понимаю, что это не просто структурный паттерн, а паттерн рефакторинга структуры классов?
                +1
                «паттерн рефакторинга структуры классов?»

                Да, это прием управления эффектом мультиплексии структурных элементов.
                Но не ограничивается этим и содержит ряд инвариантов (ограничений) которые показывают границы структуры компонента.
                — «независимость иерархий» лишь логическое понятие, достигаемое:
                а) откладыванием связывания до момента выполнения.
                б) однонаправленной ассоциацией. ThreadSheduler знает о Вариантах реализации, обратная зависимость нежелательна.
                в) ThreadSheduler_Implementation всей функциональностью подчинен только потребностям ThreadSheduler. Т.е явное отношение «Ведущий — ведомый».
                г) ThreadSheduler не самодостаточен без ThreadSheduler_Implementation. Т.е все время пока существует ThreadSheduler ссылка на ThreadSheduler_Implementation должна быть не Null.
                д) ThreadSheduler_Implementation используется только ThreadSheduler. Отношение Public use Private. Здесь можно сравнить с «жемчужиной». Все сторонние компоненты видят только «раковину» т.е ThreadSheduler, внутри которого кристаллизуется «жемчужина» ThreadSheduler_Implementation. По мере возрастания «ценности жемчужины» она впосле может отправится в самостоятельное плавание.

                При соблюдении всех инвариантов «мост» приобретает четкие границы, и явно отражает структуру единого компонента, а не масштабируется до любых горизонтальных стрелочек.

                Про адаптеры:
                В приведенном примере UnixPTS, WindowsPTS и.д. естественно не наследуются и никак не зависят от ThreadSheduler_Implementation. Просто имена немного неудачные, сами по себе это отдельные самодостаточные «компоненты», которые лишь используются для платформенно-зависимой реализации.
                Т.е по факту у нас будет некие ThreadSheduler_UnixPTSImplementation реализующие нужды ThreadSheduler (это первично), в своей внутренней реализации использующие соответствующие платформенные примитивы. Т.е адартер вторичен и скрыт во внутренней логике.
                Связь ThreadSheduler -> ThreadSheduler_UnixPTSImplementation будет «Мостом»
                Связь ThreadSheduler_UnixPTSImplementation -> UnixPTS будет адаптером.
                0
                «Но здесь важно помнить, что шаблоны не определяют качество модели предметной области»

                Как сказать. Например, тот же мост — будет ВСЕГДА портить качество модели предметной области, а не будет НИКОГДА улучшать. В то время как замена моста, некоторыми другими шаблонами, при большей продуманности модели предметной области будет лучше сказываться на качестве модели предметной области.
                  0
                  Почему?
                    0
                    Потому что когда мы строим модель предметной области — мы не оперируем такими вещами как абстракция или реализация. И соответственно, нам не может даже в голову прийти отделить их, сделать из них две сущности. Другое дело, когда за другой сущностью (реализацией) прячется просто еще мало осознанный и не спроектированный участок. Когда вы его спроектируете окажется, что это совсем не реализация, а набор других сущностей. И я уже разбирал один пример, и там показательно, что реализацией Фигур назвали (условно) Художника (того кто умеет рисовать). Ну, это же дико, если мы строим модель предметной области — то она и близко не построена. Могу разобрать и друге примеры, подходы будут другие — но все эти примеры покажут именно это — т.к. в ООП — ну нельзя НИКОГДА разделять абстракцию от реализации, если очень хочется то это указывает лишь на то, что проектирование выполнено криво. А «Мост» как бы дезавуирует этот момент.
                      0
                      Приведу просто несколько цитат о проектировании.

                      Есть однако и правило о нарушении правил: прежде чем нарушать правило, необходимо его как следует выучить.
                      Робин Вильямс

                      В реальном мире однако, мы вначале обнаруживаем частный случай и лишь затем открываем общую абстракцию.
                      Бертран Мейер

                      Создание сложных, хорошо проработанных моделей предметных областей возможно, и они стоят затраченного на них труда, но прогресс не идет плавно и последовательно, переход к действительно глубокой по смыслу модели — это огромный качественный скачок, который требует радикального изменения архитектуры. Не пытайтесь искуственно вызвать такой скачок, большую часть работы занимают мелкие фрагментированные изменения приближающие вас к пониманию предметной области.
                      Качественный скачок требует полномасштабного перепроектирования и смелости.

                      Эрик Эванс

                      Удача — это основа проектирования.
                      Бранч Рики

                      Все модели неверны, но некоторые из них полезны.
                      Джордж Бокс

                      Программы на самом деле не существует. Совершенно нормально планировать работу так, будто вы строите объект недвижимости, — просто не удивляйтесь, когда кто-либо потребует его передвинуть.
                      Чед Лавиль
                        0
                        "Мы не смогли ввести собственные правила, вот и страдаем"
                        +1
                        Речь идет о книге А. Шаллоуей, Дж. Тротт — Шаблоны проектирования.

                        Каким образом нотация БедныйХудожник.Нарисуй(МиллионАлыхРоз) решает проблему того, что реальное рисование выполняется c сторонних программам?..

                        Художник (компонент) предоставляет другому компоненту API (набор графических примитивов), для реализации которых он полагается на сторонние программы. Отношение Фигура — Кисть в исходной постановке скрыто в Художнике. Акцент идет на вариантах реализации кисти.

                        Итоговая формулировка А. Шаллоуей, Дж. Тротт позиционирует «мост» как прием управления мультиплексией связей.

                        Давайте боротся нее с формулировкой GoF (абстракция, реализация), а просто найдем «зерно», отражающее суть приема.

                        Обвинять мультиплексор в том, что он помешал реализовать супер-процессор убийцу Intel как то не очевидно. При проектировании думать надо о процессоре, а не логическом вентиле.

                          0
                          Формулировка «моста» на которой остановились А. Шаллоуей, Дж. Тротт в своей книге

                          Классы производные от абстрактного класса, должны использовать множество классов реализации этой абстракции. Не вызывая при этом лавинообразного увеличения кол-ва классов в системе
                            0
                            Вы понимаете, что обеспечить отсутствие лавинообразного увеличения кол-ва классов в системе можно разным способами, среди который мост будет наименее предпочтительным?

                            И потом, как же не учитывать формулировку разделения абстракции и реализации? Хорошо, вот если бы мы договорились, что нужно просто выделять разные ответственности классов — это было бы другое дело. Но тогда не было бы такого абсурда как «метод DrawRectangle() находится на функциональном уровне, а DrawLine() на уровне платформенных реализаций» — это методы одной ответственности, и должны быть вместе. Искусственно их разделяя вы нарушаете модель предметной области. Ради чего? А просто потому, что «Мост».
                              0
                              как же не учитывать формулировку разделения абстракции и реализации?

                              Оставьте формулировку оригинального GoF. Вы не первый у кого она вызывает вопросы, но люди не пытаются отрицать, а пытаются понять что имелось в виду.
                              К тому же не забываем 3-е бандитов были практиками С++, а один ученым и практиком Smalltalk. Прочитайте про шаблон Мulticast, в течении нескольких лет 3-е видели шаблон, а программист на Smalltalk в упор не понимал о чем речь. По «мосту» эти четверо хотя бы понимали друг друга.
                              Даю подсказку посмотрите на структурные схемы Моста, Стратегии, Состояния. Удалите все названия классов и попробуйте найти отличия. GoF нас дрессируют объясняя очень важные вещи простым языком наметафор, «рефлексов».

                              Метод DrawRectangle() находится на функциональном уровне, а DrawLine() на уровне платформенных реализаций

                              Вы пишите «финансовый калькулятор для расчета рисков» который работает во множестве браузеров/платформ, которому лишь нужно пару фигурных стрелочек, да прямоугольников для подсветки важный чисел.
                              Вы серьезно думаете что клиент вам заплатит за год который вы потратите на построение универсальной графической модели?
                              «Мост» это не самоцель — это начальный шаг, пожалуйста развивайте модель, GoF вас к этому и подталкивает неужели не понятно он говорит «запутались в связях своей модели, давайте разорвем иерархии минимизируем зависимость и начнем все сначала».
                              0
                              Вот кстати, как нужно решить ваш пример с бумажными/компьютерными моделям. Эти четыре модели бумажная, компьютерная, тестовая, серийная — это некий способ представить автомобиль. Что в этом случае говорит нам ООП? А то, что автомобиль может выполнять 4 разные роли. Роли описываются интерфейсами. Поэтому создаем Iбумажная, Iкомпьютерная, Iтестовая, Iсерийная.

                              Эти интерфейсы все 4 — должен реализовать автомобиль. (а не легковой, грузовой автомобиль как у вас). Но эти интерфейсы автомобиль может реализовать только в общем виде, без специфики легкового, грузового транспорта. Поэтому в легковом/грузовом реализации будут уточнены/переопределены. Но мы видим, что порождать искусственную вторую иерархию в отдельных классах совершенно излишнее. Общая каркасная логика должна содержаться в автомобиле. Тем более что интерфейсы Iбумажная, Iкомпьютерная, Iтестовая, Iсерийная во многом пересекаются между собой. Кому-то может показаться, что тогда автомобиль много чего в себе содержит — но на самом деле, если будем уточнять реализация бумажной/компьютерной/… будет разделена на части по другому принципу, с выделением чертежей/постановки экспериментов/модели процессов производства.

                              Теперь мы видим, что Мост в данном случае выделяет искусственно иерархию в отдельный класс. В тоже время, проблема доопределения частностей для легковой/грузовой машины никуда не пропадает. И это доопределение неестественным образом происходит ни как переопределеня интерфейсов в моем решении, а как выделение новых методов в абстракции. Вспоминаем «метод DrawRectangle() находится на функциональном уровне, а DrawLine() на уровне платформенных реализаций» — вот что на самом деле происходит — DrawRectangle() — это доопределение специфики прямоугольника. Но происходит это доопределение неявно, т.е. не отражено в программе. А явно сделать нельзя, т.к. класс искусственно поделили на два.
                                0
                                Вот кстати, как нужно решить

                                Реализация автомобиля инженерами Автоваза почему то отличается от реализации автомобиля инженерами BMW.

                                Поймите не каждая система из 10 миллионов логических вентилей автоматически станет процессором. Но без знания базовых элементов вы тем более не сможете спроектировать процессор.

                                Если у вас есть уникальные идеи по архитектуре ПО, то оформите их по аналогии в описанием паттернов. Назначение, Имя, Техника, Примеры (можно Open Source).
                                Это будет более конструктивно.
                                  0
                                  На мой взгляд все уникальные идеи и «логические вентили» сформулированы у Г. Буча в его «Объектно-ориентированный анализ и проектирование». Этим я и пользуюсь. Это достаточно более чем. Ну может быть еще про UML почитать полезно. А все эти паттерны, DDD — это не более чем хорошо забытое классическое ООП — так сказать болезненный переход специалистов от структурного подхода к объектно-ориентированному. Просто даже интересно читать — с каким пиететом пишут книги о DDD («перевернуло мышление», «теперь не так отношусь к классическому ООП — над которым раньше потешался»). А ведь просто нужно было ООП изучить.

                                  Я же не призываю использовать что то новое — все о чем я говорю — это элементарно давно изложено.

                                  Вся теория паттернов — это излишество — болезнь от ума. Да есть полезные паттерны, но есть и не полезные. Но даже если оставить полезные — то они легко получаются с комбинации наследования/агрегации и еще ряда приемов классического ООП, которое Г. Буч более чем самодостаточно описал.
                                    0
                                    «Серебрянной пули» нет.

                                    Чтобы не возникало ощущения противоречия между великолепной и фундаментальной работой Г. Буча и паттернами «Банды четырех» добавлю, что паттерны рекомендованы Бучем к ознакомлению после главы 4. Которая посвящена принципам классификации/категоризации.

                                    Большая работа была проведена в области каталогизации программного обеспечения, в частности, в области классификации идиом, механизмов и принципов. С этой точки зрения большой интерес представляют работы Гамма и др. (Gamma et al.) [E 1995],
                                    Г. Буч
                                      0
                                      Противоречия в «большом» то нет, но вот излишество есть. Ну не вижу я там чего-то принципиально нового, так некая сборная солянка, после которой возникает ощущения безвкусия. Но это да — видимо на любителя. Но если уж «верить» паттернам — то нужно быть ДО ЭТОГО вооруженным классикой ООП. Тогда по крайней мере можно отличить некачественное и в 99,9% ненужное применение шаблона «Мост».
                                        0
                                        Вот, кстати, паттерн «Мост» должно иметь четкую ассоциацию с денормализацией. Понятно, что на денормализацию иногда идут, вот с Мостом — та же история.
                        0
                        Спасибо! Пожалуй, самая полезная статья в серии «мостов».

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое