Qual é a diferença entre o padrão de ponte e o padrão de estratégia?

114

Tentei ler muitos artigos sobre dofactory , wikipedia e muitos sites. Não tenho ideia das diferenças entre o padrão de ponte e o padrão de estratégia.

Eu sei que ambos separam uma abstração de sua implementação e podem alterar a implementação em tempo de execução.

Mas ainda não sei em que situação devo usar estratégia ou em que situação devo usar bridge.

Krirk
fonte

Respostas:

66

Semântica. Da wikipedia :

O diagrama de classes UML para o padrão Strategy é igual ao diagrama para o padrão Bridge. No entanto, esses dois padrões de design não são os mesmos em sua intenção. Enquanto o padrão Strategy se destina ao comportamento, o padrão Bridge se destina à estrutura.

O acoplamento entre o contexto e as estratégias é mais estreito do que o acoplamento entre a abstração e a implementação no padrão Bridge.

Pelo que entendi, você está usando o padrão de estratégia ao abstrair o comportamento que pode ser fornecido de uma fonte externa (por exemplo, o config pode especificar para carregar algum conjunto de plug-in) e está usando o padrão de ponte quando usa as mesmas construções para tornar seu código um pouco mais organizado. O código real será muito semelhante - você está apenas aplicando os padrões por motivos ligeiramente diferentes .

Kent Boogaart
fonte
3
então posso dizer que estou usando o padrão de estratégia para ser capaz de abstrair o comportamento enquanto também faço o código parecer mais organizado como no padrão de ponte ... ou, estou usando o padrão de ponte para tornar o código mais limpo e também porque ele me permite para abstrair o comportamento como no padrão de estratégia? e eu estaria certo?
user20358
1
A diferença entre os dois está apenas em sua intenção. Então, acho que podemos dizer com segurança que, porque ambos usam a mesma ideia e oferecem a mesma flexibilidade, os dois padrões são funcionalmente iguais.
Elz
3
A UML da Bridge é bem diferente em minha cópia do livro GoF. Esta ferramenta é capaz de distinguir Bridge de Estratégia.
Fuhrmanator
1
A Wikipedia costuma ser uma referência terrível. Com razão, essa desinformação foi removida da página. en.wikipedia.org/w/…
Fuhrmanator
2
O que entendi é que a mesma técnica é usada para abstrair uma implementação (estratégia) ou para abstrair uma interface (ponte). Comportamentos de troca de estratégia, interfaces de troca de ponte (isso, em última análise, permite que implementações com tais interfaces sejam trocadas). Em outras palavras, o Bridge cria uma interface padronizada de um lado e conecta as implementações com diferentes interfaces do outro.
Nikaas de
55

O padrão Bridge é um padrão estrutural (COMO VOCÊ CONSTRÓI UM COMPONENTE DE SOFTWARE?). O padrão de estratégia é um padrão dinâmico (COMO VOCÊ DESEJA EXECUTAR UM COMPORTAMENTO NO SOFTWARE?).

A sintaxe é semelhante, mas os objetivos são diferentes:

  • Estratégia : você tem mais maneiras de fazer uma operação; com estratégia, você pode escolher o algoritmo em tempo de execução e pode modificar uma única estratégia sem muitos efeitos colaterais em tempo de compilação;
  • Bridge : você pode dividir a hierarquia de interface e classe, uni-la com uma referência abstrata (ver explicação )
Alepuzio
fonte
3
então, se a sintaxe for semelhante, eu estaria correto ao dizer que estou usando qualquer um desses padrões para executar um comportamento de software de uma maneira particular e também porque quero construir o componente dessa maneira para que também pareça legal?
user20358
11

Estratégia:

  • Contexto vinculado à Estratégia: A classe de contexto (possivelmente Abstract, mas não realmente uma interface! Já que você deseja encapsular um comportamento específico e não a implementação inteira) saberia / conteria a referência da interface da estratégia e a implementação para invocar o comportamento da estratégia em isto.
  • Intent é a capacidade de trocar o comportamento em tempo de execução

    class Context {
    
         IStrategy strategyReference;
    
         void strategicBehaviour() {
    
            strategyReference.behave();
         }
    
    }
    

Ponte

  • Abstração não vinculada à implementação: A interface de abstração (ou classe abstrata com a maior parte do comportamento abstrato) não saberia / conteria a referência da interface de implementação
  • A intenção é separar completamente a Abstração da Implementação

    interface IAbstraction {
    
        void behaviour1();
    
        .....
    
    }
    
    interface IImplementation {
    
         void behave1();
    
         void behave2();
    
         .....
    
    }
    
    class ConcreteAbstraction1 implements IAbstraction {
    
          IImplementation implmentReference;
    
          ConcreteAbstraction1() {
    
               implmentReference = new ImplementationA() // Some implementation
    
          }
    
          void behaviour1() {
    
                implmentReference.behave1();
    
          }
    
          .............
    
    }
    
    class ConcreteAbstraction2 implements IAbstraction {
    
          IImplementation implmentReference;
    
          ConcreteAbstraction1() {
    
               implmentReference = new ImplementationB() // Some Other implementation
    
          }
    
          void behaviour1() {
    
                implmentReference.behave2();
    
          }
    
          .............
    
    }
    
MEER
fonte
10

Eu estava pensando o mesmo, mas recentemente tive que usar bridge e percebi que bridge é usar estratégia e adicionar abstração ao contexto para que mais tarde você possa fazer mais alterações sem alterar o cliente. Ao usar o Strategy sem a abstração, o design não é tão flexível e pode exigir alterações para o cliente posteriormente. Mas ao usar a ponte inteira, o design se torna ainda mais flexível. Aqui você pode ver como passar de Estratégia para Bridge oferece mais flexibilidade. Também assumimos que agora "visa" e "master" não estão disponíveis apenas em cartões, mas também em telefones e chips; e se usarmos bridge é muito mais fácil adicionar esse suporte.

Estratégia VS Bridge

Orhan
fonte
9

Ponte : (um padrão estrutural)

O padrão de ponte desacopla abstração e implementação e permite que ambas variem independentemente.

Use este padrão quando:

  1. Abstrações e implementações não foram decididas em tempo de compilação
  2. Abstrações e implementações devem ser alteradas independentemente
  3. Mudanças na implementação da abstração não devem afetar o aplicativo do chamador
  4. O cliente deve ser isolado dos detalhes de implementação.

Estratégia: (padrão comportamental)

Os padrões de estratégia permitem que você alterne entre vários algoritmos de uma família de algoritmos em tempo de execução.

Use o padrão de estratégia quando:

  1. São necessárias várias versões de algoritmos
  2. O comportamento da classe deve ser alterado dinamicamente em tempo de execução
  3. Evite declarações condicionais

Postagens relacionadas:

Quando você usa o padrão de ponte? Como é diferente do padrão do adaptador?

Exemplo do mundo real do padrão de estratégia

Ravindra babu
fonte
4

Tipos de padrão de design

  • Comportamental: padrões caracterizam as maneiras pelas quais classes ou objetos interagem e distribuem responsabilidades
  • Estrutural: padrões lidam com a composição de classes ou objetos.
  • Criacional: os padrões estão preocupados com o processo de criação do objeto.

Ponte (estrutural)

Desacople uma abstração de sua implementação para que cada uma possa variar. independentemente. insira a descrição da imagem aqui

Pegue um controle remoto. O controle remoto possui botões 1-6. Esta é a classe concreta do diagrama acima. Cada botão funcionará de forma diferente dependendo se o controle remoto é usado para uma TV ou DVD. A funcionalidade de cada botão é abstraída da implementação pela interface do implementador.

Isso nos permite mudar a forma como o controle remoto funcionará para cada dispositivo.

Estratégia (comportamental)

Defina uma família de algoritmos, encapsule cada um e torne-os intercambiáveis. insira a descrição da imagem aqui

Na estratégia, se estivéssemos olhando para o cenário remoto. O "estado" é todo o controle remoto que trocamos alterando a referência de estado do contexto. O "concreteStateA" (controle remoto da TV) "concreteStateB" (controle remoto do DVD).

Leitura adicional:

Daniel
fonte
3
  1. O Strategy Pattern é usado para decisões comportamentais, enquanto o Bridge Pattern é usado para decisões estruturais.

  2. O Brigde Pattern separa os elementos abstratos dos detalhes de implementação, enquanto o Strategy Pattern se preocupa em tornar os algoritmos mais intercambiáveis.

Padrão de Estratégia em UML

Padrão Brigde em UML

Padrão de estratégia em Swift:

protocol PrintStrategy {
   func print(_ string: String) -> String
}

class Printer {
   let strategy: PrintStrategy

   init(strategy: PrintStrategy) {
      self.strategy = strategy
    }

  func print(_ string: String) -> String {
     return self.strategy.print(string)
  }
}

class UpperCaseStrategy: PrintStrategy {
    internal func print(_ string: String) -> String {
        return string.uppercased()
    }
}

class LowerCaseStrategy: PrintStrategy {
    internal func print(_ string: String) -> String {
        return string.lowercased()
    }
}

var lower = Printer(strategy: LowerCaseStrategy())
lower.print("I love Software Patterns")

var upper = Printer(strategy: UpperCaseStrategy())
upper.print("I love Software Patterns")

Padrão Brigde em Swift:

protocol Appliance {
   func run()
}

protocol Switch {
   let appliance: Appliance {get set}
   func turnOn()
}

class RemoteControl: Switch {
   var appliance: Appliance

   init(appliance: Appliance) {
       self.appliance = appliance
   }

   internal func turnOn() {
      appliance.run()
   }
}

class TV: Appliance {
   internal func run() {
      print("TV is ON")
   }
}

class Stereo: Appliance {
   internal func run() {
      print("Stereo is ON")
   }
}

var tvRemote = RemoteControl.init(appliance: TV())
tvRemote.turnOn()

var stereoRemote = RemoteControl.init(appliance: Stereo())
stereoRemote.turnOn()
Joan Disho
fonte
como é que apenas o padrão de estratégia é mais "intercambiável". Uma vez que codificamos para interface, não para implementação, podemos trocar as implementações em estratégia ou ponte, como você demonstrou em seu exemplo de código, trocando Stereocom TVe o código simplesmente funciona.
denis631
2

Somando-se à resposta de willcodejavaforfood, eles podem ser os mesmos, em implementação. No entanto, você usa a estratégia para trocar estratégias, como estratégia de classificação, enquanto usa a ponte para fazer a ponte entre as implementações de dois objetos, digamos, um wrapper de banco de dados e um adaptador de rede para que o código do cliente possa usar qualquer um deles trabalhando na mesma API. Então, o nome realmente diz tudo

Robert Gould
fonte
1

Do wiki no padrão de estratégia

O diagrama de classes UML para o padrão Strategy é igual ao diagrama para o padrão Bridge. No entanto, esses dois padrões de design não são os mesmos em sua intenção. Enquanto o padrão Strategy se destina ao comportamento, o padrão Bridge se destina à estrutura.

O acoplamento entre o contexto e as estratégias é mais estreito do que o acoplamento entre a abstração e a implementação no padrão Bridge.

willcodejavaforfood
fonte
Você poderia elaborar a última frase?
gstackoverflow
1

Apenas para adicionar ao que já foi dito sobre a comparação de padrões (diferença de intenção, ...): o padrão Bridge também é intencionalmente estruturado para permitir que o lado da hierarquia de abstração varie. Em linguagens como C #, isso pode significar que você tem uma base de abstração que contém métodos virtuais como uma forma de permitir variações pretendidas que não causam problemas para os consumidores existentes. Fora isso, os dois padrões podem parecer idênticos na maior parte.

Burt
fonte
1

O padrão de estratégia é usado quando você deseja conectar algoritmo ou estratégia em tempo de execução. Como categoria de padrão também implica que se trata do comportamento dos objetos. Por outro lado, a ponte é um padrão estrutural e lida com a hierarquia estrutural dos objetos. Ele separa a abstração da implementação, introduzindo uma abstração refinada entre elas. A abstração refinada pode ser confundida com a estratégia de tempo de execução conectada (padrão In Strategy). O padrão de ponte lida com os aspectos estruturais, fornecendo um mecanismo para evitar a criação de n número de classes.

Pranav Sharma
fonte
1

Para o padrão de estratégia, apenas a implementação varia.

Suponha que a classe A esteja usando a classe B, que possui várias implementações disponíveis. Portanto, nesse caso, B seria abstrato com a implementação real fornecida em tempo de execução. Este é o padrão de estratégia

Agora, se o próprio A é abstrato. Ambos A e B podem variar. Você usaria o padrão Bridge.

Ritesh Tyagi
fonte
0

Acho que há uma pequena diferença entre eles no contexto em que estão sendo usados.

Eu uso o padrão Bridge para separar conceitos ortogonais que pertencem a um conceito maior - para deixá-los variar independentemente. Geralmente envolve várias abstrações.

IMO, o padrão de estratégia é mais simples ou mais plano. Ele serve para OCP com certeza, mas não necessariamente para fazer parte de outro conceito maior como o padrão Bridge.

stdout
fonte