Бридж против стратегии-паттерна

Я знаю, что этот вопрос задавался много раз, но я провел какое-то исследование и до сих пор не получил его, возможно, вы мне поможете: как уже много раз говорилось, UML почти одинаков. Кроме того, реализация и идея более или менее одинаковы: вместо подтипирования вы определяете интерфейс, который инкапсулирует некоторую логику и позволяет перейти к абстрактному. Так что, даже ребята из Microsoft-Blog

https://blogs.msdn.microsoft.com/gyanjadal/2015/01/05/difference-between-strategy-and-bridge-patterns/ сообщает:

Простой ответ: "Они похожи, но разные". Реализации похожи, но намерения разные. Чтобы дать аналогию, городской автобус и школьный автобус - оба похожие транспортные средства, но они используются для различных целей. Один используется для перевозки людей между различными частями города в качестве пригородной службы. Другой используется для перевозки детей в школы.

"Если это звучит как утка и выглядит как утка, но намеревается стать лебедем, это может быть любой из них", - вот что я читаю здесь.

Так как я все еще не получил это, я копал глубже:

https://social.msdn.microsoft.com/Forums/en-US/08775d39-2de0-4598-8872-df21f681b7b3/strategy-vs-bridge-patterns?forum=architecturegeneral

Эта тема также не добавляет ничего нового, кроме:

Они оба выглядят одинаково на поверхности и для меня. Основное отличие, которое я вижу, состоит в том, что в паттерне Bridge абстракция является ЧАСТЬЮ объекта, но в паттерне Стратегия абстракция выполняется объектом.

Но, если мы прочитаем определение стратегии:

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

Нет ничего определенного, как применяется Стратегия. Он также может быть интерфейсом на абстрактном уровне, точно таким же, как обычная реализация стратегии, как LINQ-Orderby и т. Д.

Еще один интерес к этой теме:

http://game-engineering.blogspot.ch/2008/07/bridge-pattern-vs-strategy-pattern.html

Основная часть этого курса:

Вы говорите "Стратегия", когда хотите изменить поведение, и вы делаете это не путем написания различных объектов, а путем введения иерархии классов. Вы говорите "Мост", когда ожидаете, что вы будете менять как интерфейс, так и реализацию. В обоих случаях вы предоставляете гибкость для меняющейся реализации; в Bridge вы также ожидаете, что интерфейс изменится.

Это, наверное, главное отличие? Так как Реализация и Абстракция очень слабо связаны, я могу изменить Интерфейс Реализатора, и Абстракция не заботится? Это звучит разумно, но разве тогда абстракция тоже не изменится, так как они как-то связаны? Разве это не разрушит все другие принципы, такие как сокрытие информации и СУХОЙ?

Я также просмотрел много примеров, которые я не добавляю здесь, ради места, и я не смог найти Пример одного из этих шаблонов, который я не смог бы изменить, чтобы соответствовать другому. Будь то через интерфейс-свойство или просто параметр.

Я что-то здесь пропустил? Возможно, у кого-нибудь есть пример НАСТОЯЩЕЙ ЖИЗНИ "Я хотел использовать стратегию, но Мост просто подошел лучше", или наоборот?

Изменить: Почему я оправдываю собственную тему для этой темы (снова)? Прежде всего, принятым ответом упомянутой темы является следующий

Насколько я понимаю, вы используете шаблон стратегии, когда абстрагируете поведение, которое может быть предоставлено из внешнего источника (например, config может указывать на загрузку некоторой сборки плагина), и вы используете шаблон моста, когда используете те же конструкции, чтобы сделать ваш код немного аккуратнее. Фактический код будет выглядеть очень похоже - вы просто применяете шаблоны по несколько другим причинам.

В предыдущих объяснениях я уже указывал, что абстрагирование поведения от внешнего источника - это в точности определение стратегии и паттерна моста.

Также

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

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

Я думаю, что любой, кто читает всю тему, видит, что в этой теме есть нечто большее, чем эти 2 предложения.

2 ответа

Решение

Википедия UML-диаграмма для паттерна моста:

WML-диаграмма для Bridge Посмотрите на мой ответ в связанном вопросе для основных различий:

В чем разница между образцом моста и образцом стратегии?

Основное отличие: абстракция и реализация могут меняться независимо.

Что касается других ваших запросов:

Это, наверное, главное отличие? Так как Реализация и Абстракция очень слабо связаны, я могу изменить Интерфейс Реализатора, и Абстракция не заботится? Это звучит разумно, но разве тогда абстракция тоже не изменится, так как они как-то связаны?

Посмотрите на приведенный ниже пример кода @

Когда вы используете шаблон моста? Чем он отличается от шаблона адаптера?

Несмотря на то, что пример написан на Java, это легко понять разработчикам на C#.

В связанном примере:

Vehicle            : Abstraction
Car                : Re-defined Abstraction
Truck              : Re-defined Abstraction
Implementor        : GearShifter
ConcreteImplementor: ManualGearShifter  
ConcreteImplementor: AutoGearShifter 

Keynotes:

  1. Сейчас Vehicle а также GearShifter может измениться самостоятельно.

  2. Если Vehicle только изменения Car а также Truck должны быть изменены.

  3. Если GearShifter только изменения ManualGearShifter а также AutoGearShifter нужно изменить.

  4. поскольку Vehicle (абстракция) содержит GearShifter (реализация) через состав, изменения в GearShifter не влияет Vehicle

  5. поскольку GearShifter (исполнитель) не содержит или ссылается Vehicle (абстракция), изменения в абстракции не влияют на реализацию.

РЕДАКТИРОВАТЬ:

В паттерне Bridge представлены две иерархии ортогональных классов - одна для абстракции, а другая для исполнителя, которая может быть изменена независимо, без зависимости от других.

Я проверил оригинальную книгу шаблонов дизайна, чтобы увидеть, как авторы определяли шаблон моста. Их реальный пример демонстрирует случай, когда иерархии как абстракции, так и иерархии могут изменяться независимо (т.е. могут быть введены новые подклассы для абстракции; новые подклассы могут быть введены для реализаций). Их пример касается библиотеки окон, которая может работать для разных оконных систем. В исходном примере авторы использовали другую оконную систему от IBM, но я полагаю, что хорошей текущей аналогией были бы другие оконные менеджеры Linux (GNOME, KDE и т. Д.). Итак, представьте себе абстракцию Window и две реализации для GNOME и KDE. А теперь представьте, что вы хотите добавить новый подкласс Window, TransparentWindow. TransparentWindow расширяет Window, так же как GNOMEWindow и KDEWindow. Но вы также должны предоставить элементы для TransparentWindow: GNOMETransparentWindow и KDETransparentWindow. Иерархия начинает выглядеть грязной. Представьте себе новый тип окна или новый оконный менеджер - XFCE. Чтобы избежать сложных иерархий, они вводят шаблон Bridge и разделяют две иерархии (т. Е. TransparentWindow расширяет Window; GNOMEWindow и KDEWindow расширяют WindowImpl). Мне кажется, что сложно определить интерфейс для реализации, поскольку иерархии абстракций должны будут определять свои операции, используя только этот интерфейс. Вот пример изучения паттерна Bridge, который мне понравился, и он мне понравился, потому что он не использует искусственные классы ConcreteImplementor1 и ConcreteImplementor2. Когда дело доходит до реальных примеров, я думаю, что я видел этот шаблон в реализации Selenium WebDriver, но сейчас я не уверен на 100%.

В шаблоне стратегии действия "Родителя" для конкретной операции постоянны, тогда как действия "Дочернего" могут варьироваться. Однако в паттерне "Мост" действия Родителя и Дитя могут различаться.

Так, например,

public class Ticket {
    
    Date dateOfTravel;
    int distance;
    Vehicle vehicle;
    Seat  seat;
    
    public float getTotalFare(){
         //depends on 
               //Distance
               //Vehicle - whether Vehicle is AC or non-AC. 
               //Seat - based on the location of the Seat.
     
        //Fare = vehicleBaseFare*seatMultiplier*distance

    }
    
}

В приведенном выше примере варианты зависят от Родителя (расстояние), а также от детей (Автомобиль и Сиденье). Итак, здесь и Vehicle, и Seat действуют как Bridge.

Вот здесь

public class Vehicle {

   TrackingDevice device;

   public Coordinates getCoordinates(){
       return device.getCoordinates();
   }
}

Здесь роль Родителя была постоянной, т.е. ничего! Итак, это был паттерн Стратегии.

Другие вопросы по тегам