Pregunta

¿Alguien ha usado alguna vez el Patrón de puente en una aplicación del mundo real? Si es así, ¿cómo lo usaste? ¿Soy yo, o es solo el Patrón Adaptador con una pequeña inyección de dependencia en la mezcla? ¿Realmente merece su propio patrón?

¿Fue útil?

Solución

Se usa un ejemplo clásico del patrón Bridge en la definición de formas en un entorno de UI (consulte Bridge patrón de entrada de Wikipedia ). El patrón Bridge es un compuesto del < a href = "http://en.wikipedia.org/wiki/Template_method_pattern" rel = "noreferrer"> Plantilla y Patrones de estrategia .

Es una vista común de algunos aspectos del patrón Adaptador en el patrón Puente. Sin embargo, para citar este artículo :

  

A primera vista, el patrón Puente se parece mucho al patrón Adaptador en el sentido de que una clase se utiliza para convertir un tipo de interfaz a otra. Sin embargo, la intención del patrón Adaptador es hacer que una o más interfaces de clases se vean iguales a las de una clase en particular. El patrón Bridge está diseñado para separar la interfaz de una clase de su implementación para que pueda variar o reemplazar la implementación sin cambiar el código del cliente.

Otros consejos

Hay una combinación de Federico's y las respuestas de John .

Cuándo:

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

Refactorizar a:

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

El patrón de Puente es una aplicación del antiguo consejo, "prefiere la composición sobre la herencia". Se vuelve útil cuando debe subclasificar diferentes tiempos de manera ortogonal entre sí. Digamos que debe implementar una jerarquía de formas de colores. No subclase Forma con Rectángulo y Círculo y luego subclase Rectángulo con Rectángulo Rojo, Rectángulo Azul y Rectángulo Verde y lo mismo para Círculo, ¿verdad? Preferiría decir que cada Forma tiene un Color e implementar una jerarquía de colores, y ese es el Patrón de Puente. Bueno, no implementaría una "jerarquía de colores", pero se entiende la idea ...

Cuándo:

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

Refactorizar a:

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

El adaptador y el puente están ciertamente relacionados, y la distinción es sutil. Es probable que algunas personas que piensan que están usando uno de estos patrones realmente estén usando el otro patrón.

La explicación que he visto es que Adaptador se usa cuando intentas unificar las interfaces de algunas clases incompatibles que ya existen . El Adaptador funciona como una especie de traductor de implementaciones que podrían considerarse heredadas .

Mientras que el patrón Bridge se usa para código que es más probable que sea greenfield. Está diseñando el puente para proporcionar una interfaz abstracta para una implementación que debe variar, pero también define la interfaz de esas clases de implementación.

Los controladores de dispositivos son un ejemplo citado a menudo de Bridge, pero yo diría que es un Bridge si está definiendo las especificaciones de interfaz para los proveedores de dispositivos, pero es un Adaptador si está tomando controladores de dispositivos existentes y haciendo un envoltorio -clase para proporcionar una interfaz unificada.

Entonces, en cuanto al código, los dos patrones son muy similares. En cuanto a los negocios, son diferentes.

Consulte también http://c2.com/cgi/wiki?BridgePattern

En mi experiencia, Bridge es un patrón recurrente bastante frecuente, porque es la solución siempre que haya dos dimensiones ortogonales en el dominio . P.ej. formas y métodos de dibujo, comportamientos y plataformas, formatos de archivo y serializadores, etc.

Y un consejo: siempre piense en los patrones de diseño desde la perspectiva conceptual , no desde la perspectiva de implementación. Desde el punto de vista correcto, Bridge no se puede confundir con Adapter, porque resuelven un problema diferente, y la composición es superior a la herencia no por sí misma, sino porque permite manejar las preocupaciones ortogonales por separado.

La intención de Bridge y Adapter es diferente y necesitamos ambos patrones por separado.

Patrón de puente:

  1. Es un patrón estructural
  2. La abstracción y la implementación no están vinculadas en tiempo de compilación
  3. Abstracción e implementación: ambas pueden variar sin impacto en el cliente
  4. Utiliza la composición sobre la herencia.

Use el patrón Puente cuando:

  1. Desea vinculación en tiempo de ejecución de la implementación,
  2. Tiene una proliferación de clases como resultado de una interfaz acoplada y numerosas implementaciones,
  3. Desea compartir una implementación entre varios objetos,
  4. Necesita mapear jerarquías de clases ortogonales.

La respuesta de @ John Sonmez muestra claramente la efectividad del patrón de puente para reducir la jerarquía de clases.

Puede consultar el siguiente enlace de documentación para obtener una mejor visión del patrón del puente con el ejemplo de código

Patrón de adaptador :

  1. It permite que dos interfaces no relacionadas trabajen juntas a través de los diferentes objetos, posiblemente desempeñando el mismo papel.
  2. Modifica la interfaz original.

Diferencias clave:

    El
  1. adaptador hace que las cosas funcionen después de haber sido diseñadas; Bridge los hace funcionar antes que ellos.
  2. Bridge está diseñado por adelantado para permitir que la abstracción y la implementación varíen independientemente . El Adaptador se actualiza para que las clases no relacionadas funcionen juntas.
  3. La intención: Adaptador permite que dos interfaces no relacionadas funcionen juntas. Bridge permite que la abstracción y la implementación varíen independientemente.

Pregunta SE relacionada con el diagrama UML y el código de trabajo:

Diferencia entre el patrón del puente y el patrón del adaptador

Artículos útiles:

puente de creación de código fuente artículo de patrón

adaptador de creación de fuentes artículo de patrón

puente de journaldev artículo de patrón

EDIT:

Ejemplo del mundo real del patrón de puente (según la sugerencia de meta.stackoverflow.com, ejemplo de sitio de documentación incorporado en esta publicación ya que la documentación se pondrá al sol)

El patrón de puente desacopla la abstracción de la implementación para que ambos puedan variar independientemente. Se ha logrado con la composición en lugar de la herencia.

Patrón de puente UML de Wikipedia:

 Patrón de puente UML de Wikipedia

Tiene cuatro componentes en este patrón.

Abstracción : define una interfaz

RefinedAbstraction : Implementa la abstracción:

Implementor : define una interfaz para la implementación

ConcreteImplementor : implementa la interfaz Implementor.

El quid del patrón de Bridge: Dos jerarquías de clases ortogonales que usan composición (y no herencia). La jerarquía de abstracción y la jerarquía de implementación pueden variar de forma independiente. La implementación nunca se refiere a la abstracción. Abstracción contiene la interfaz de implementación como miembro (a través de la composición). Esta composición reduce un nivel más de jerarquía de herencia.

Caso de uso de palabras reales:

Permitir que diferentes vehículos tengan ambas versiones del sistema de cambio manual y automático.

Exampl

He usado el patrón de puente en el trabajo. Programo en C ++, donde a menudo se le llama modismo PIMPL (puntero a la implementación). Se ve así:

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

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

En este ejemplo, clase A contiene la interfaz y clase Aimpl contiene la implementación.

Un uso para este patrón es exponer solo algunos de los miembros públicos de la clase de implementación, pero no otros. En el ejemplo, solo se puede llamar a Aimpl :: foo () a través de la interfaz pública de A , pero no a Aimpl :: bar ()

Otra ventaja es que puede definir Aimpl en un archivo de encabezado separado que no necesita ser incluido por los usuarios de A . Todo lo que tiene que hacer es utilizar una declaración directa de Aimpl antes de definir A y mover las definiciones de todas las funciones miembro que hacen referencia a pImpl en el archivo .cpp Esto le permite mantener privado el encabezado Aimpl y reducir el tiempo de compilación.

Para poner un ejemplo de forma en el código:

#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;
}

El resultado es:

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

Observe la facilidad con la que se pueden agregar nuevos colores y formas al sistema sin provocar una explosión de subclases debido a permutaciones.

para mí, lo considero un mecanismo en el que puedes intercambiar interfaces. En el mundo real, es posible que tenga una clase que pueda usar más de una interfaz, Bridge le permite intercambiar.

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);
}
}
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top