Domanda

Qualcuno ha mai usato Bridge Pattern in un'applicazione del mondo reale? Se è così, come lo hai usato? Sono io, o è solo il modello dell'adattatore con una piccola iniezione di dipendenza lanciata nel mix? Merita davvero il suo modello?

È stato utile?

Soluzione

Un classico esempio del modello Bridge viene utilizzato nella definizione delle forme in un ambiente UI (vedi Bridge schema voce Wikipedia ). Il modello Bridge è un composito del < a href = "http://en.wikipedia.org/wiki/Template_method_pattern" rel = "noreferrer"> Template e modelli di strategia.

È una vista comune alcuni aspetti del modello Adapter nel modello Bridge. Tuttavia, per citare da questo articolo :

  

A prima vista, il modello Bridge assomiglia molto al modello Adapter in quanto una classe viene utilizzata per convertire un tipo di interfaccia in un altro. Tuttavia, l'intento del modello Adapter è di rendere le interfacce di una o più classi uguali a quelle di una determinata classe. Il modello Bridge è progettato per separare l'interfaccia di una classe dalla sua implementazione in modo da poter variare o sostituire l'implementazione senza modificare il codice client.

Altri suggerimenti

Esiste una combinazione di Federico's e risposte di John .

Quando:

                   ----Shape---
                  /            \
         Rectangle              Circle
        /         \            /      \
BlueRectangle  RedRectangle BlueCircle RedCircle

Rifattore in:

          ----Shape---                        Color
         /            \                       /   \
Rectangle(Color)   Circle(Color)           Blue   Red

Il modello Bridge è un'applicazione del vecchio consiglio, "preferisce la composizione rispetto all'eredità". È utile quando devi sottoclassare diverse volte in modo ortogonale tra loro. Supponiamo che tu debba implementare una gerarchia di forme colorate. Non sottoclasceresti Shape con Rectangle e Circle e poi sottoclasser Rectangle con RedRectangle, BlueRectangle e GreenRectangle e lo stesso per Circle, vero? Preferiresti dire che ogni Forma ha un Colore e implementare una gerarchia di colori, e questo è il Pattern Bridge. Bene, non implementerei una "gerarchia di colori", ma avrai l'idea ...

Quando:

        A
     /     \
    Aa      Ab
   / \     /  \
 Aa1 Aa2  Ab1 Ab2

Rifattore in:

     A         N
  /     \     / \
Aa(N) Ab(N)  1   2

Adapter e Bridge sono sicuramente correlati e la distinzione è sottile. È probabile che alcune persone che pensano di utilizzare uno di questi schemi stiano effettivamente utilizzando l'altro modello.

La spiegazione che ho visto è che Adapter viene utilizzato quando si tenta di unificare le interfacce di alcune classi incompatibili che esistono già . L'adattatore funziona come una sorta di traduttore per implementazioni che potrebbero essere considerate legacy .

Considerando che il modello Bridge viene utilizzato per il codice che ha più probabilità di essere greenfield. Stai progettando il Bridge per fornire un'interfaccia astratta per un'implementazione che deve variare, ma definisci anche l'interfaccia di quelle classi di implementazione.

I driver di dispositivo sono un esempio spesso citato di Bridge, ma direi che è Bridge se si definiscono le specifiche dell'interfaccia per i fornitori di dispositivi, ma è un adattatore se si prendono driver di dispositivo esistenti e si crea un wrapper -classare per fornire un'interfaccia unificata.

Quindi, per quanto riguarda il codice, i due modelli sono molto simili. Per quanto riguarda il business, sono diversi.

Vedi anche http://c2.com/cgi/wiki?BridgePattern

Nella mia esperienza, Bridge è un modello abbastanza spesso ricorrente, perché è la soluzione ogni volta che ci sono due dimensioni ortogonali nel dominio . Per esempio. forme e metodi di disegno, comportamenti e piattaforme, formati di file e serializzatori e così via.

E un consiglio: pensa sempre ai modelli di progettazione dal punto di vista concettuale , non dal punto di vista dell'implementazione. Dal giusto punto di vista, Bridge non può essere confuso con Adapter, perché risolvono un problema diverso e la composizione è superiore all'eredità non a causa di se stessa, ma perché consente di gestire separatamente le preoccupazioni ortogonali.

L'intento di Bridge e Adattatore è diverso e abbiamo bisogno di entrambi i modelli separatamente.

Schema del ponte:

  1. È un modello strutturale
  2. Astrazione e implementazione non sono vincolate al momento della compilazione
  3. Astrazione e implementazione: entrambi possono variare senza impatto sul client
  4. Usa la composizione sull'ereditarietà.

Usa il modello Bridge quando:

  1. Si desidera il binding runtime dell'implementazione,
  2. Hai una proliferazione di classi risultante da un'interfaccia accoppiata e numerose implementazioni,
  3. Desideri condividere un'implementazione tra più oggetti,
  4. Devi mappare le gerarchie di classi ortogonali.

La risposta di John Sonmez mostra chiaramente l'efficacia del modello a ponte nella riduzione della gerarchia di classi.

È possibile fare riferimento al seguente collegamento alla documentazione per ottenere una migliore comprensione del modello di bridge con l'esempio di codice

Schema adattatore :

  1. consente a due interfacce non correlate di lavorare insieme attraverso i diversi oggetti, possibilmente giocando lo stesso ruolo.
  2. Modifica l'interfaccia originale.

Differenze chiave:

  1. Adattatore fa funzionare le cose dopo che sono state progettate; Bridge li fa funzionare prima che lo siano.
  2. Bridge è progettato in anticipo per consentire a l'astrazione e l'implementazione di variare indipendentemente . Adapter è stato adattato per consentire alle classi non correlate di lavorare insieme.
  3. L'intento: Adattatore consente a due interfacce non correlate di lavorare insieme. Bridge consente all'astrazione e all'implementazione di variare in modo indipendente.

Domanda SE correlata con diagramma UML e codice di lavoro:

Differenza tra il modello Bridge e il modello Adapter

Articoli utili:

bridge di creazione di sorgenti articolo modello

adattatore per la generazione di sorgenti articolo modello

journaldev bridge articolo modello

Modifica

Esempio nel mondo reale di Bridge Pattern (Come suggerito da meta.stackoverflow.com, esempio di sito di documentazione incorporato in questo post poiché la documentazione sta per tramontare)

Il modello a ponte disaccoppia l'astrazione dall'implementazione in modo che entrambi possano variare in modo indipendente. È stato realizzato con la composizione piuttosto che con l'eredità.

UML modello bridge da Wikipedia:

 Bridge pattern UML da Wikipedia

Hai quattro componenti in questo modello.

Astrazione : definisce un'interfaccia

RefinedAbstraction : implementa l'astrazione:

Implementor : definisce un'interfaccia per l'implementazione

ConcreteImplementor : implementa l'interfaccia Implementor.

Il punto cruciale del modello Bridge: Due gerarchie di classi ortogonali che usano la composizione (e nessuna eredità). La gerarchia di astrazione e la gerarchia di implementazione possono variare in modo indipendente. L'implementazione non si riferisce mai all'astrazione. L'astrazione contiene l'interfaccia di implementazione come membro (attraverso la composizione). Questa composizione riduce un ulteriore livello di gerarchia ereditaria.

Caso d'uso di parole reali:

Abilita diversi veicoli ad avere entrambe le versioni del sistema di cambio manuale e automatico.

exampl

Ho usato il modello bridge al lavoro. Programma in C ++, dove spesso viene chiamato linguaggio PIMPL (puntatore all'implementazione). Sembra così:

class A
{
public: 
  void foo()
  {
    pImpl->foo();
  }
private:
  Aimpl *pImpl;
};

class Aimpl
{
public:
  void foo();
  void bar();
};  

In questo esempio classe A contiene l'interfaccia e classe Aimpl contiene l'implementazione.

Un uso per questo modello è quello di esporre solo alcuni dei membri pubblici della classe di implementazione, ma non altri. Nell'esempio solo Aimpl :: foo () può essere chiamato attraverso l'interfaccia pubblica di A , ma non Aimpl :: bar ()

Un altro vantaggio è che puoi definire Aimpl in un file di intestazione separato che non deve essere incluso dagli utenti di A . Tutto quello che devi fare è utilizzare una dichiarazione in avanti di Aimpl prima di definire A e spostare le definizioni di tutte le funzioni membro che fanno riferimento a pImpl in il file .cpp. Ciò ti dà la possibilità di mantenere privata l'intestazione Aimpl e ridurre i tempi di compilazione.

Per inserire un esempio di forma nel codice:

#include<iostream>
#include<string>
#include<cstdlib>

using namespace std;

class IColor
{
public:
    virtual string Color() = 0;
};

class RedColor: public IColor
{
public:
    string Color()
    {
        return "of Red Color";
    }
};

class BlueColor: public IColor
{
public:
    string Color()
    {
        return "of Blue Color";
    }
};


class IShape
{
public:
virtual string Draw() = 0;
};

class Circle: public IShape
{
        IColor* impl;
    public:
        Circle(IColor *obj):impl(obj){}
        string Draw()
        {
            return "Drawn a Circle "+ impl->Color();
        }
};

class Square: public IShape
{
        IColor* impl;
    public:
        Square(IColor *obj):impl(obj){}
        string Draw()
        {
        return "Drawn a Square "+ impl->Color();;
        }
};

int main()
{
IColor* red = new RedColor();
IColor* blue = new BlueColor();

IShape* sq = new Square(red);
IShape* cr = new Circle(blue);

cout<<"\n"<<sq->Draw();
cout<<"\n"<<cr->Draw();

delete red;
delete blue;
return 1;
}

L'output è:

Drawn a Square of Red Color
Drawn a Circle of Blue Color

Nota la facilità con cui nuovi colori e forme possono essere aggiunti al sistema senza portare a un'esplosione di sottoclassi a causa di permutazioni.

per me lo considero un meccanismo in cui è possibile scambiare interfacce. Nel mondo reale potresti avere una classe che può utilizzare più di un'interfaccia, Bridge ti consente di scambiare.

Bridge design pattern we can easily understand helping of service and dao layer.

Dao layer -> create common interface for dao layer ->
public interface Dao<T>{
void save(T t);
}
public class AccountDao<Account> implement Dao<Account>{
public void save(Account){
}
}
public LoginDao<Login> implement Dao<Login>{
public void save(Login){
}
}
Service Layer ->
1) interface
public interface BasicService<T>{
    void save(T t);
}
concrete  implementation of service -
Account service -
public class AccountService<Account> implement BasicService<Account>{
 private Dao<Account> accountDao;
 public AccountService(AccountDao dao){
   this.accountDao=dao;
   }
public void save(Account){
   accountDao.save(Account);
 }
}
login service- 
public class LoginService<Login> implement BasicService<Login>{
 private Dao<Login> loginDao;
 public AccountService(LoginDao dao){
   this.loginDao=dao;
   }
public void save(Login){
   loginDao.save(login);
 }
}

public class BridgePattenDemo{
public static void main(String[] str){
BasicService<Account> aService=new AccountService(new AccountDao<Account>());
Account ac=new Account();
aService.save(ac);
}
}
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top