Pergunta

Alguém já usou o Ponte Padrão em uma aplicação no mundo real? Se sim, como você usá-lo? É de mim, ou é apenas o Padrão Adapter com um pouco injeção de dependência jogado na mistura? Será que realmente merece seu próprio padrão?

Foi útil?

Solução

Um exemplo clássico do padrão Bridge é usado na definição de formas em um ambiente UI (veja a Ponte padrão Wikipedia entrada). O padrão Bridge é um composta do < a href = "http://en.wikipedia.org/wiki/Template_method_pattern" rel = "noreferrer"> Template e padrões Estratégia .

É uma visão comum alguns aspectos do padrão Adapter no padrão Bridge. No entanto, para citar este artigo :

À primeira vista, o padrão Bridge se parece muito com o padrão Adapter em que uma classe é usado para converter um tipo de interface para outra. No entanto, a intenção do padrão Adapter é fazer com que interfaces de uma ou mais classes' olhar o mesmo que o de uma classe particular. O padrão Bridge é projetado para separar interface de uma classe a partir de sua implementação para que possa modificar ou substituir a implementação sem alterar o código do cliente.

Outras dicas

Há uma combinação de de Federico e respostas de John.

Quando:

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

Refactor para:

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

O padrão Bridge é um aplicativo do velho conselho: "prefiro composição sobre herança". Torna-se útil quando você deve subclasse tempos diferentes de maneiras que são ortogonais entre si. Digamos que você deve implementar uma hierarquia de formas coloridas. Você não iria Forma subclasse com retângulo e círculo e, em seguida, subclasse do retângulo com redRectangle, BlueRectangle e GreenRectangle eo mesmo para Circle, você faria? Você preferiria dizer que cada Forma tem a cor e para implementar uma hierarquia de cores, e que é o padrão Bridge. Bem, eu não iria implementar uma "hierarquia de cores", mas você começa a idéia ...

Quando:

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

Refactor para:

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

Adaptador e Ponte está certamente relacionado, ea distinção é sutil. É provável que algumas pessoas que pensam que eles estão usando um desses padrões estão realmente usando o outro padrão.

A explicação que eu vi é que o adaptador é usado quando você está tentando unificar as interfaces de algumas classes incompatíveis que já existe . As funções de adaptador como uma espécie de tradutor para implementações que poderiam ser consideradas legado .

Considerando que o padrão Bridge é usado para o código que é mais provável que seja greenfield. Você está projetando a ponte para fornecer uma interface abstrata para uma implementação que precisa variar, mas você também definir a interface dessas classes de implementação.

Os drivers de dispositivo é um exemplo freqüentemente citado da ponte, mas eu diria que é uma ponte se você está definindo a especificação de interface para fornecedores de dispositivos, mas é um adaptador se você está tomando drivers de dispositivo existentes e fazer um invólucro de classe para fornecer uma interface unificada.

Assim código-sábio, os dois padrões são muito semelhantes. Business-sábio, eles são diferentes.

Veja também http://c2.com/cgi/wiki?BridgePattern

Em minha experiência, a ponte é um padrão, muitas vezes recorrentes, porque é a solução sempre que existem duas dimensões ortogonais no domínio . Por exemplo. formas e métodos de desenho, comportamentos e plataformas, formatos de arquivo e serializers e assim por diante.

E um conselho: sempre pensar em padrões de projeto a partir da perspectiva conceitual , e não a partir da perspectiva de implementação. Do ponto de vista correto, Ponte não pode ser confundida com adaptador, porque eles resolver um problema diferente, ea composição é superior a herança não por causa do amor de si mesmo, mas porque permite lidar com preocupações ortogonais separadamente.

A intenção do Ponte e O adaptador é diferente e precisamos de ambos os padrões separadamente.

Ponte padrão:

  1. É um padrão estrutural
  2. Abstraction e implementação não estão vinculados em tempo de compilação
  3. Abstraction e implementação - ambos podem variar sem impacto no cliente
  4. Usa composição sobre herança.

Use o padrão Bridge quando:

  1. Você quer ligação da aplicação run-time,
  2. Você tem uma proliferação de classes resultantes de uma interface acoplada e inúmeras implementações,
  3. Você deseja compartilhar uma implementação entre vários objetos,
  4. Você precisa mapear hierarquias de classe ortogonais.

@ resposta John Sonmez mostra claramente a eficácia do padrão de ponte na redução da hierarquia de classes.

Você pode consultar abaixo link da documentação para obter uma melhor visão sobre padrão de ponte com exemplo de código

Adaptador padrão :

  1. permite que duas interfaces não relacionados ao trabalho em conjunto através de diferentes objetos, possivelmente jogando mesmo papel.
  2. Ele modifica interface original.

Principais diferenças:

  1. O adaptador faz as coisas funcionarem após eles são projetados; Ponte torna o trabalho antes que eles são.
  2. Ponte é projetado up-front para deixar o abstração e a implementação variar independentemente . Adaptador é adaptado para fazer aulas não relacionados trabalhar juntos.
  3. A intenção: Adaptador permite que duas interfaces independentes para trabalhar juntos. Ponte permite abstração e implementação de variar independentemente.

questão SE relacionada com UML diagrama e código de trabalho:

Diferença entre padrão Bridge e adaptador padrão

artigos úteis:

sourcemaking ponte artigo padrão

sourcemaking adaptador artigo padrão

journaldev ponte padrão

EDIT:

Padrão Ponte exemplo do mundo real (como por meta.stackoverflow.com sugestão, exemplo site da documentação incorporados neste cargo desde documentação vai sol-set)

Ponte desacopla padrão abstração da implementação de modo que ambos possam variar independentemente. Ele foi alcançado com a composição em vez de herança.

Ponte padrão UML da Wikipedia:

 UML padrão Bridge da Wikipedia

Você tem quatro componentes neste padrão.

Abstraction: Define uma interface

RefinedAbstraction: Ele implementa a abstração:

Implementor: Define uma interface para a implementação

ConcreteImplementor:. Ele implementa a interface Implementor

The crux of Bridge pattern : Duas hierarquias de classe ortogonais usando composição (e nenhuma herança). A hierarquia e a hierarquia de Implementação da abstracção pode variar de forma independente. Implementação nunca se refere abstracção. Abstracção contém interface de Aplicação como um membro (através da composição). Esta composição reduz mais um nível de hierarquia de herança.

palavra real Caso de uso:

Ativar veículos diferentes para ter ambas as versões do sistema manual e engrenagem automática.

código Exemplo:

/* Implementor interface*/
interface Gear{
    void handleGear();
}

/* Concrete Implementor - 1 */
class ManualGear implements Gear{
    public void handleGear(){
        System.out.println("Manual gear");
    }
}
/* Concrete Implementor - 2 */
class AutoGear implements Gear{
    public void handleGear(){
        System.out.println("Auto gear");
    }
}
/* Abstraction (abstract class) */
abstract class Vehicle {
    Gear gear;
    public Vehicle(Gear gear){
        this.gear = gear;
    }
    abstract void addGear();
}
/* RefinedAbstraction - 1*/
class Car extends Vehicle{
    public Car(Gear gear){
        super(gear);
        // initialize various other Car components to make the car
    }
    public void addGear(){
        System.out.print("Car handles ");
        gear.handleGear();
    }
}
/* RefinedAbstraction - 2 */
class Truck extends Vehicle{
    public Truck(Gear gear){
        super(gear);
        // initialize various other Truck components to make the car
    }
    public void addGear(){
        System.out.print("Truck handles " );
        gear.handleGear();
    }
}
/* Client program */
public class BridgeDemo {    
    public static void main(String args[]){
        Gear gear = new ManualGear();
        Vehicle vehicle = new Car(gear);
        vehicle.addGear();

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

        gear = new ManualGear();
        vehicle = new Truck(gear);
        vehicle.addGear();

        gear = new AutoGear();
        vehicle = new Truck(gear);
        vehicle.addGear();
    }
}

saída:

Car handles Manual gear
Car handles Auto gear
Truck handles Manual gear
Truck handles Auto gear

Explicação:

  1. Vehicle é uma abstração.
  2. Car e Truck são duas implementações concretas de Vehicle.
  3. Vehicle define um método abstrato: addGear().
  4. Gear é implementador da interface
  5. ManualGear e AutoGear são duas implementações de Gear
  6. Vehicle contém a interface implementor em vez de implementar a interface. Compositon de interface de implementador é ponto crucial desse padrão:. Ele permite abstração e implementação para variar independentemente
  7. Car e Truck definir implementação (redefinido abstração) de abstração: addGear(): Contém Gear - Ou Manual ou Auto

Use caso (s) para o padrão Bridge :

  1. Abstraction e Implementação pode mudar independentes uns dos outros e eles não estão vinculados em tempo de compilação
  2. Mapa hierarquias ortogonais - um para Abstraction e um para Implementação .

Eu tenho usado o padrão de ponte no trabalho. Eu programa em C ++, onde muitas vezes é chamado o idioma Pimpl (ponteiro para implementação). Parece que este:

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

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

Neste exemplo class A contém a interface, e class Aimpl contém a implementação.

Um uso para esse padrão é expor apenas algumas das membros públicos da classe de implementação, mas não outros. No exemplo apenas Aimpl::foo() pode ser chamado através da interface pública de A, mas não Aimpl::bar()

Outra vantagem é que você pode definir Aimpl em um arquivo de cabeçalho separado que não precisam ser incluídos pelos usuários do A. Tudo que você tem a fazer é usar uma declaração para a frente de Aimpl antes A é definido, e mover as definições de todos as funções de membro fazendo referência pImpl no arquivo .cpp. Isto dá-lhe a capacidade de manter o cabeçalho Aimpl privada, e reduzir o tempo de compilação.

Para colocar de forma exemplo em 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;
}

A saída é:

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

Observe a facilidade com que novas cores e formas podem ser adicionados ao sistema sem levar a uma explosão de subclasses devido à permutações.

para mim eu penso nisso como um mecanismo onde você pode trocar interfaces. No mundo real, você pode ter uma classe que pode usar mais de uma interface, ponte permite que você troque.

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top