¿Cuál es la diferencia entre el patrón puente y el patrón estratégico?


114

Intenté leer muchos artículos sobre dofactory , wikipedia y muchos sitios. No tengo idea de las diferencias entre el patrón de puente y el patrón de estrategia.

Sé que ambos desacoplan una abstracción de su implementación y pueden cambiar la implementación en tiempo de ejecución.

Pero todavía no sé en qué situación debería utilizar la estrategia o en qué situación debería utilizar el puente.

Respuestas:


66

Semántica. De wikipedia :

El diagrama de clases de UML para el patrón de estrategia es el mismo que el diagrama para el patrón de puente. Sin embargo, estos dos patrones de diseño no son iguales en su intención. Mientras que el patrón de estrategia está destinado al comportamiento, el patrón de puente está destinado a la estructura.

El acoplamiento entre el contexto y las estrategias es más estrecho que el acoplamiento entre la abstracción y la implementación en el patrón Bridge.

Según tengo entendido, está usando el patrón de estrategia cuando está abstrayendo el comportamiento que podría proporcionarse desde una fuente externa (por ejemplo, la configuración podría especificar cargar algún ensamblaje de complemento), y está usando el patrón de puente cuando usa las mismas construcciones para hacer su código un poco más ordenado. El código real se verá muy similar: solo está aplicando los patrones por razones ligeramente diferentes .


3
Entonces, ¿puedo decir que estoy usando el patrón de estrategia para poder abstraer el comportamiento y al mismo tiempo hacer que el código se vea más ordenado como en el patrón de puente ... o, estoy usando el patrón de Puente para hacer el código más ordenado y también porque me permite al comportamiento abstracto como en el patrón de estrategia? y estaría en lo cierto?
user20358

1
La diferencia entre los dos está solo en su intención. Así que supongo que podríamos decir con seguridad que, debido a que ambos usan la misma idea y ofrecen la misma flexibilidad, los dos patrones son funcionalmente iguales.
Elz

3
El UML de Bridge es bastante diferente en mi copia del libro GoF. Esta herramienta puede distinguir Bridge de Strategy.
Fuhrmanator

1
Wikipedia es a menudo una referencia terrible. Con razón, esa información errónea se eliminó de la página. en.wikipedia.org/w/…
Fuhrmanator

2
La forma en que lo entiendo es que se usa la misma técnica para abstraer una implementación (estrategia) o para abstraer una interfaz (puente). La estrategia intercambia comportamientos, Bridge intercambia interfaces (esto finalmente permite intercambiar implementaciones con tales interfaces). En otras palabras, Bridge crea una interfaz estandarizada en un lado y conecta implementaciones con diferentes interfaces en el otro.
Nikaas

55

El patrón Bridge es un patrón estructural (¿CÓMO SE CONSTRUYE UN COMPONENTE DE SOFTWARE?). El patrón de estrategia es un patrón dinámico (¿CÓMO QUIERES EJECUTAR UN COMPORTAMIENTO EN SOFTWARE?).

La sintaxis es similar pero los objetivos son diferentes:

  • Estrategia : tiene más formas de realizar una operación; con la estrategia, puede elegir el algoritmo en tiempo de ejecución y puede modificar una sola estrategia sin muchos efectos secundarios en tiempo de compilación;
  • Puente : puede dividir la jerarquía de interfaz y clase, unirla con una referencia abstracta (ver explicación )

3
Entonces, si la sintaxis es similar, ¿estaría en lo correcto al decir que estoy usando cualquiera de esos patrones para ejecutar un comportamiento de software de una manera particular y también porque quiero construir el componente de esa manera para que también se vea ordenado?
user20358

11

Estrategia:

  • Contexto vinculado a la estrategia: la clase de contexto (posiblemente abstracto, pero no realmente una interfaz, ya que desea encapsular un comportamiento específico y no la implementación completa) conocería / contendría la referencia de la interfaz de la estrategia y la implementación para invocar el comportamiento de la estrategia en eso.
  • La intención es la capacidad de intercambiar comportamientos en tiempo de ejecución

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

Puente

  • Abstracción no vinculada a la implementación: la interfaz de abstracción (o clase abstracta con la mayor parte del resumen de comportamiento) no conocería / contendría la referencia de la interfaz de implementación
  • La intención es desacoplar completamente la abstracción de la implementación

    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();
    
          }
    
          .............
    
    }
    

10

Estaba pensando lo mismo, pero recientemente tuve que usar bridge y me di cuenta de que bridge es usar estrategia y agregar abstracción al contexto para que luego puedas hacer más cambios sin cambiar el cliente. Cuando se usa la estrategia sin la abstracción, el diseño no es tan flexible y puede requerir cambios para el cliente más adelante. Pero cuando se usa todo el puente, el diseño se vuelve aún más flexible. Aquí puede ver cómo pasar de la estrategia al puente ofrece más flexibilidad. También asumimos que ahora "visa" y "master" no solo están disponibles en tarjetas, sino también en teléfonos y chips; y si usamos bridge es mucho más fácil agregar ese soporte.

Estrategia VS Bridge


9

Puente : (un patrón estructural)

El patrón de puente desacopla la abstracción y la implementación y permite que ambas varíen de forma independiente.

Utilice este patrón cuando:

  1. Las abstracciones e implementaciones no se han decidido en tiempo de compilación
  2. Las abstracciones y las implementaciones deben cambiarse de forma independiente
  3. Los cambios en la implementación de la abstracción no deberían afectar la aplicación de la persona que llama
  4. El cliente debe estar aislado de los detalles de implementación.

Estrategia: (patrón de comportamiento)

Los patrones de estrategia le permiten cambiar entre varios algoritmos de una familia de algoritmos en tiempo de ejecución.

Utilice el patrón de estrategia cuando:

  1. Se requieren múltiples versiones de algoritmos
  2. El comportamiento de la clase debe cambiarse dinámicamente en tiempo de ejecución
  3. Evite las declaraciones condicionales

Artículos Relacionados:

¿Cuándo usas el patrón de puente? ¿En qué se diferencia del patrón del adaptador?

Ejemplo del mundo real del patrón de estrategia


4

Tipos de patrones de diseño

  • Comportamiento: los patrones caracterizan las formas en que las clases u objetos interactúan y distribuyen la responsabilidad.
  • Estructural: los patrones se ocupan de la composición de clases u objetos.
  • Creacional: los patrones se preocupan por el proceso de creación de objetos.

Puente (estructural)

Desacople una abstracción de su implementación para que cada una pueda variar. independientemente. ingrese la descripción de la imagen aquí

Toma un control remoto. El control remoto tiene botones 1-6. Esta es la clase concreta en el diagrama de arriba. Cada botón funcionará de manera diferente dependiendo de si el control remoto se usa para un televisor o DVD. La funcionalidad de cada botón se extrae de la implementación por parte de la interfaz del implementador.

Esto nos permite cambiar cómo funcionará el control remoto para cada dispositivo.

Estrategia (conductual)

Definir una familia de algoritmos, encapsular cada uno y hacerlos intercambiables. ingrese la descripción de la imagen aquí

En estrategia, si estuviéramos mirando el escenario remoto. El "estado" es el control remoto completo que intercambiamos cambiando la referencia de estado del contexto. El "concreteStateA" (control remoto de TV) "concreteStateB" (control remoto de DVD).

Lectura adicional:


3
  1. El patrón de estrategia se usa para decisiones de comportamiento, mientras que el patrón de puente se usa para decisiones estructurales.

  2. Brigde Pattern separa los elementos abstractos de los detalles de implementación, mientras que Strategy Pattern se ocupa de hacer que los algoritmos sean más intercambiables.

Patrón de estrategia en UML

Patrón de Brigde en UML

Patrón de estrategia en 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")

Patrón de Brigde en 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()

cómo es que solo el patrón de estrategia es más "intercambiable". Dado que codificamos para la interfaz, no para la implementación, podemos intercambiar las implementaciones en estrategia o puente, como demostró en su ejemplo de código, intercambiando Stereocon TVy el código simplemente funciona.
denis631

2

Agregando a la respuesta de willcodejavaforfood, pueden ser iguales, en implementación. Sin embargo, usa la estrategia para intercambiar estrategias como la estrategia de clasificación, mientras que usa el puente para unir las implementaciones de dos objetos, por ejemplo, un contenedor de base de datos y un adaptador de red para que el código del cliente pueda usar cualquiera de los dos trabajando contra la misma API. Entonces, el nombre lo dice todo


1

De la wiki sobre el patrón de estrategia

El diagrama de clases de UML para el patrón de estrategia es el mismo que el diagrama para el patrón de puente. Sin embargo, estos dos patrones de diseño no son iguales en su intención. Mientras que el patrón de estrategia está destinado al comportamiento, el patrón de puente está destinado a la estructura.

El acoplamiento entre el contexto y las estrategias es más estrecho que el acoplamiento entre la abstracción y la implementación en el patrón Bridge.


¿Podría elaborar la última frase?
gstackoverflow

1

Solo para agregar a lo que ya se ha dicho sobre la comparación de patrones (diferencia de intención, ...): el patrón Bridge también está estructurado intencionalmente para permitir que varíe el lado de la jerarquía de abstracción. En lenguajes como C #, esto podría implicar que tiene una base de abstracción que contiene métodos virtuales como una forma de permitir variaciones deseadas que no causen problemas a los consumidores existentes. Aparte de eso, los dos patrones pueden parecer idénticos en su mayor parte.


1

El patrón de estrategia se utiliza cuando desea conectar un algoritmo o estrategia en tiempo de ejecución. Como categoría de patrón también implica que se ocupa del comportamiento de los objetos. Por otro lado, el puente es un patrón estructural y se ocupa de la jerarquía estructural de los objetos. Desacopla la abstracción de la implementación al introducir una abstracción refinada entre ellas. La abstracción refinada se puede confundir con la estrategia de tiempo de ejecución enchufada (patrón In Strategy). El patrón de puente se ocupa de los aspectos estructurales proporcionando un mecanismo para evitar la creación de n número de clases.


1

Para el patrón de estrategia, solo varía la implementación.

Supongamos que la clase A está usando la clase B, que tiene varias implementaciones disponibles. Entonces, en ese caso, B sería abstracto con la implementación real proporcionada en tiempo de ejecución. Este es el patrón de estrategia

Ahora bien, si A en sí mismo es abstracto. Tanto A como B pueden variar. Usaría el patrón de puente.


0

Creo que hay una ligera diferencia entre ellos en el contexto en el que se utilizan.

Utilizo el patrón Bridge para separar conceptos ortogonales que pertenecen a uno más grande, para que varíen independientemente. Por lo general, implica múltiples abstracciones.

En mi opinión, el patrón de estrategia es más simple o más plano. Sirve para OCP con seguridad, pero no necesariamente para ser parte de otro concepto más grande como el patrón Bridge.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.