Різниця між схемою моста та схемою адаптера


125

Яка різниця між моделями Bridge та Adapter?


Можливо, вам слід запропонувати уточнюючу редакцію, щоб направити дискусію на те, де ви вважаєте, що вам потрібно використовувати те чи інше.
Джефф Вілкокс


Ніяке пояснення тут ніколи не замінить читання
Шаблонів

Відповіді:


173

"Адаптер змушує роботу працювати після їх розробки; Bridge змушує їх працювати до того, як вони є. [GoF, p219]"

Ефективно, модель Адаптер корисна, коли у вас є існуючий код, будь то третя сторона чи внутрішня компанія, але поза вашим контролем або іншим чином не змінюється, щоб повністю відповідати інтерфейсу, який вам потрібен. Наприклад, у нас є SuperWeaponsArray, який може керувати прекрасним набором пристроїв судного дня.

public class SuperWeaponsArray {
  /*...*/

  public void destroyWorld() {
    for (Weapon w : armedWeapons) {
      w.fire();
    }
  }
}

Чудово. За винятком того, що ми розуміємо, що в нашому арсеналі є ядерний пристрій, який значно передує перетворенню на інтерфейс зброї. Але нам би хотілося, щоб це працювало тут ... так що ми робимо ... вклинимо це!

NukeWeaponsAdaptor - заснований на нашому класі Nuke, але експортує інтерфейс Weapon. Солодке, зараз ми точно можемо знищити світ. Це здається трохи хитрощів, але воно змушує працювати.


Модель Bridge - це те, що ви реалізуєте на передньому плані - якщо ви знаєте, що у вас є дві ортогональні ієрархії, він забезпечує спосіб роз’єднання інтерфейсу та реалізації таким чином, що ви не отримаєте шалену кількість класів. Скажімо, у вас є:

Типи файлових об'єктів MemoryMappedFile та DirectReadFile. Скажімо, ви хочете мати можливість читати файли з різних джерел (можливо, Linux та Windows). Bridge допомагає вам уникнути завивки:

MemoryMappedWindowsFile MemoryMappedLinuxFile DirectReadWindowsFile DirectReadLinuxFile


9
Чи можна скористатися більш абстрактним переліком коду? приклад занадто конкретний і заплутаний.

36
@omouse схвалено, приклад коду насправді не є тим, що робить цю відповідь суттєвою . Для дбайливого читача є достатня кількість покажчиків , щоб почати розрізняти візерунки, так що все у всьому - це є хороший відповідь.
Віктор Фараздагі

15
Ви могли б надати якийсь фактичний приклад коду для мостового шаблону?
Хайме Хаблуцель

2
Я думаю, що багато людей прийшли до цього питання так само, як і я - вони, ймовірно, вже розглядали код для двох моделей, але визнали деякі схожість і зрозуміли, що їх розуміння може бути ще більше закріплено, встановивши дві схеми. Рядок про міст, який допомагає вам уникнути завершення роботи з конкретними файлами для Windows та Linux, принаймні для мене допоміг зрозуміти, чим « Реалізатор » мостового візерунка ( dofactory.com/net/bridge-design-pattern ) відрізняється від "Адаптер".
Йорданія

3
"Адаптер змушує роботу працювати після їх розробки; Bridge змушує їх працювати раніше, ніж вони є." У книзі, яку я читав, не було зазначено взагалі, тому важко було їх розрізнити. Напевно, читання ГОФ вартує зусиль ...
Олександр Дерк,

15

http://en.wikipedia.org/wiki/Adapter_pattern

Шаблон адаптера стосується того, щоб ваш існуючий код працював з новою системою або інтерфейсом.

Якщо у вас є набір стандартних API фірм для веб-служб, які ви хочете запропонувати в існуючий інтерфейс розширюваності іншої програми, ви можете розглянути можливість створення набору адаптерів для цього. Зауважте, що є сіра зона, і це більше стосується того, як ви технічно визначаєте візерунок, оскільки інші візерунки, як фасад, схожі.

http://en.wikipedia.org/wiki/Bridge_pattern

Шаблон Bridge дозволить вам мати альтернативні варіанти реалізації алгоритму чи системи.

Хоча це не класичний приклад шаблону Bridge, уявіть, якби у вас було кілька реалізацій сховища даних: одна ефективна в просторі, інша - ефективна в сирому режимі ... і у вас є бізнес-приклад для пропонування як у вашому додатку, так і в рамках .

Що стосується вашого запитання, "де я можу скористатись якою схемою", відповідь є, де це має сенс для вашого проекту! Можливо, вам слід запропонувати уточнюючу редакцію, щоб направити дискусію на те, де ви вважаєте, що вам потрібно використовувати те чи інше.


14

Адаптер:

  1. Це структурна закономірність
  2. Корисно працювати з двома несумісними інтерфейсами

Діаграма UML: з дофакторної статті:

введіть тут опис зображення

Мета : визначає інтерфейс для домену, який використовує Клієнт.

Адаптер : адаптує інтерфейс Adaptee до цільового інтерфейсу.

Adaptee : визначає існуючий інтерфейс, який потребує адаптації.

Клієнт : співпрацює з об'єктами, які відповідають цільовому інтерфейсу.

Приклад:

Квадрат і прямокутник - це дві різні форми, і для отримання площі () кожного з них потрібні різні методи. Але все ж Square працює над інтерфейсом Rectangle з перетворенням деяких властивостей.

public class AdapterDemo{
    public static void main(String args[]){
        SquareArea s = new SquareArea(4);
        System.out.println("Square area :"+s.getArea());
    }
}

class RectangleArea {
    public int getArea(int length, int width){
        return length * width;
    }
}

class SquareArea extends RectangleArea {

    int length;
    public SquareArea(int length){
        this.length = length;
    }
    public int getArea(){
        return getArea(length,length);
    }
}

Міст:

  1. Це структурна структура
  2. це відокремлює абстракцію від її реалізації і обидва можуть змінюватись незалежно
  3. Це можливо, оскільки композиція була використана замість спадкування

EDIT: (відповідно до пропозиції @quasoft)

У вас є чотири компоненти в цій схемі.

  1. Абстракція : вона визначає інтерфейс

  2. RefinedAbstraction : Він реалізує абстракцію:

  3. Виконавець : Він визначає інтерфейс для реалізації

  4. ConcreteImplementor : він реалізує інтерфейс Implementor.

Фрагмент коду:

Gear gear = new ManualGear();
Vehicle vehicle = new Car(gear);
vehicle.addGear();

gear = new AutoGear();
vehicle = new Car(gear);
vehicle.addGear();

Пов’язана публікація:

Коли ви використовуєте шаблон моста? Чим вона відрізняється від моделі адаптера?

Основні відмінності: від статті про створення джерела

  1. Адаптер змушує роботу працювати після їх розробки; Міст змушує їх працювати, перш ніж вони є.
  2. Міст розроблений вперед, щоб абстракція та реалізація залежали незалежно. Адаптер переобладнаний для того, щоб зв'язати непов’язані класи разом.

Додайте у відповідь приклад автомобіля / вантажівки / передач із документів. Прекрасний приклад і аналогія.
квасофт

8

Цей пост існує досить довгий час. Однак важливо розуміти, що фасад дещо схожий на перехідник, але це не зовсім те саме. Адаптер "адаптує" існуючий клас до звичайно несумісного класу клієнтів. Скажімо, у вас є стара система робочого процесу, яку ваша програма використовує як клієнт. Ваша компанія, можливо, може замінити систему робочого процесу на нову "несумісну" (з точки зору інтерфейсів). У більшості випадків ви можете використовувати шаблон адаптера і писати код, який фактично викликає нові інтерфейси двигуна робочого процесу. Міст зазвичай використовується по-іншому. Якщо у вас фактично є система, яка потребує роботи з різними файловими системами (наприклад, локальним диском, NFS тощо), ви можете використовувати шаблон моста і створити один рівень абстракції для роботи з усіма вашими файловими системами. Це в основному буде простим випадком використання для схеми моста. Фасад та адаптер мають деякі властивості, алеФасади зазвичай використовуються для спрощення існуючого інтерфейсу / класу . У перші дні EJB не було місцевих дзвінків для EJB. Розробники завжди отримували заглушку, звужували її і називали її «псевдо-віддалено». Це часто викликало проблеми з працездатністю (особливо, коли насправді дзвонили по радіо). Досвідчені розробники використовуватимуть фасадну схему, щоб забезпечити клієнту дуже грубозернистий інтерфейс. Тоді цей фасад в свою чергу здійснюватиме декілька дзвінків до різних більш дрібних методів. Загалом це значно зменшило кількість необхідних викликів методів та підвищило продуктивність.


Хоча, здавалося б, поза межами цього питання, зважування Адаптер і Міст проти Фасаду може бути дуже доречним.
Коді

1

Міст вдосконалений адаптер. Bridge включає адаптер і додає йому додаткову гнучкість. Ось як відображають елементи відповіді Равіндри між візерунками:

      Adapter  |    Bridge
    -----------|---------------
    Target     | Abstraction
    -----------|---------------
               | RefinedAbstraction
               |
               |   This element is Bridge specific. If there is a group of 
               |   implementations that share the same logic, the logic can be placed here.
               |   For example, all cars split into two large groups: manual and auto. 
               |   So, there will be two RefinedAbstraction classes.
    -----------|--------------- 
    Adapter    | Implementor
    -----------|---------------
    Adaptee    | ConcreteImplementor

1

У верхній відповіді @James цитує речення від GoF, сторінка 219. Я думаю, що тут варто відтворити повне пояснення.

Адаптер проти мосту

Шаблони адаптера та моста мають деякі загальні ознаки. Обидва сприяють гнучкості, забезпечуючи рівень непрямості до іншого об’єкта. Обидва передбачають запити на переадресацію цього об’єкта з іншого інтерфейсу, ніж власний.

Ключова відмінність цих моделей полягає в їх намірах. Адаптер фокусується на вирішенні несумісностей між двома існуючими інтерфейсами. Він не зосереджується на тому, як реалізуються ці інтерфейси, і не розглядає, як вони можуть розвиватися незалежно. Це спосіб змусити два самостійно розроблених заняття працювати разом, не повторюючи те чи інше. Bridge, з іншого боку, мостить абстракцію та її (потенційно численні) реалізації. Він забезпечує стабільний інтерфейс для клієнтів, навіть як дозволяє змінювати класи, які його реалізують. Він також вміщує нові реалізації в міру розвитку системи.

Внаслідок цих відмінностей Adapter і Bridge часто використовуються в різних точках життєвого циклу програмного забезпечення. Адаптер часто стає необхідним, коли ви виявите, що два несумісні класи повинні працювати разом, як правило, щоб уникнути реплікації коду. Зчеплення непередбачене. На відміну від цього, користувач мосту розуміє, що абстракція повинна мати кілька реалізацій, і обидві можуть розвиватися незалежно. Схема адаптера примушує роботу працювати після їх розробки; Міст змушує їх працювати до того, як вони є. Це не означає, що Адаптер якось поступається Місту; кожен шаблон просто вирішує іншу проблему.


0

Припустимо, у вас абстрактний клас Shape з (загальним / абстрагованим) функцією малювання та Коло, яке реалізує форму. Шаблон мосту просто - це двосторонній абстракційний підхід для роз'єднання реалізації (малювання в колі) та загальної / абстрагованої функціональності (малюнок у класі Shape).

Що це насправді означає? На перший погляд це звучить як щось, що ви вже робите (через інверсію залежності). Тож не турбуйтеся про те, щоб мати меншу кількість або більш модульну базу коду. Але за цим криється трохи глибша філософія.

З мого розуміння, потреба у використанні може виникнути, коли мені потрібно додати нові класи, тісно пов'язані з поточною системою (наприклад, RedCircle або GreenCircle) і які вони відрізняються лише однією функціональністю (наприклад, кольором). І мені знадобиться модель Bridge, особливо якщо наявні системні класи (коло або форма) потрібно часто змінювати, і ви не хочете, щоб на ці зміни були впливають новоприєднані класи. Отож, тому загальна функціональність малювання абстрагується у новому інтерфейсі, щоб ви могли змінити поведінку малювання незалежно від форми або кола.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.