stringtranslate.com

Patrón de estrategia

En programación de computadoras , el patrón de estrategia (también conocido como patrón de política ) es un patrón de diseño de software de comportamiento que permite seleccionar un algoritmo en tiempo de ejecución. En lugar de implementar un único algoritmo directamente, el código recibe instrucciones de tiempo de ejecución sobre cuál de una familia de algoritmos usar. [1]

La estrategia permite que el algoritmo varíe independientemente de los clientes que lo utilicen. [2] La estrategia es uno de los patrones incluidos en el influyente libro Design Patterns de Gamma et al. [3] que popularizó el concepto de utilizar patrones de diseño para describir cómo diseñar software orientado a objetos flexible y reutilizable. Aplazar la decisión sobre qué algoritmo utilizar hasta el tiempo de ejecución permite que el código de llamada sea más flexible y reutilizable.

Por ejemplo, una clase que realiza validación de datos entrantes puede usar el patrón de estrategia para seleccionar un algoritmo de validación dependiendo del tipo de datos, la fuente de los datos, la elección del usuario u otros factores discriminatorios. Estos factores no se conocen hasta el tiempo de ejecución y pueden requerir la realización de una validación radicalmente diferente. Los algoritmos (estrategias) de validación, encapsulados por separado del objeto de validación, pueden ser utilizados por otros objetos de validación en diferentes áreas del sistema (o incluso en diferentes sistemas) sin duplicación de código .

Normalmente, el patrón de estrategia almacena una referencia al código en una estructura de datos y la recupera. Esto se puede lograr mediante mecanismos como el puntero de función nativa , la función de primera clase , clases o instancias de clase en lenguajes de programación orientados a objetos , o accediendo al almacenamiento interno de código de la implementación del lenguaje a través de la reflexión .

Estructura

Diagrama de secuencia y clase UML

Un ejemplo de diagrama de secuencia y clase UML para el patrón de diseño de estrategia. [4]

En el diagrama de clases UML anterior , la clase no implementa un algoritmo directamente. En cambio, se refiere a la interfaz para realizar un algoritmo ( ), lo que lo hace independiente de cómo se implementa un algoritmo. Las clases y implementan la interfaz, es decir, implementan (encapsulan) un algoritmo. El diagrama de secuencia UML muestra las interacciones en tiempo de ejecución: el objeto delega un algoritmo a diferentes objetos. Primero, llama a un objeto, que realiza el algoritmo y devuelve el resultado . A partir de entonces, cambia su estrategia y llama a un objeto, que realiza el algoritmo y devuelve el resultado .ContextContextStrategystrategy.algorithm()ContextStrategy1Strategy2Strategy
ContextStrategyContextalgorithm()Strategy1ContextContextalgorithm()Strategy2Context

Diagrama de clase

Patrón de estrategia en UML

[5]

Patrón de estrategia en LePUS3 (leyenda)


Estrategia y principio abierto/cerrado.

Los comportamientos de aceleración y frenado deben declararse en cada modelo de automóvil nuevo .

Según el patrón estratégico, los comportamientos de una clase no deberían heredarse. En cambio, deberían encapsularse mediante interfaces. Esto es compatible con el principio abierto/cerrado (OCP), que propone que las clases deben estar abiertas a la extensión pero cerradas a la modificación.

Como ejemplo, consideremos una clase de automóvil. Dos posibles funcionalidades para el coche son frenar y acelerar . Dado que los comportamientos de aceleración y frenado cambian con frecuencia entre modelos, un enfoque común es implementar estos comportamientos en subclases. Este enfoque tiene importantes inconvenientes; Los comportamientos de aceleración y frenado deben declararse en cada nuevo modelo de automóvil. El trabajo de gestionar estos comportamientos aumenta enormemente a medida que aumenta el número de modelos y requiere que el código se duplique entre los modelos. Además, no es fácil determinar la naturaleza exacta del comportamiento de cada modelo sin investigar el código de cada uno.

El patrón de estrategia utiliza composición en lugar de herencia . En el patrón de estrategia, los comportamientos se definen como interfaces separadas y clases específicas que implementan estas interfaces. Esto permite un mejor desacoplamiento entre el comportamiento y la clase que utiliza el comportamiento. El comportamiento se puede cambiar sin romper las clases que lo usan, y las clases pueden cambiar entre comportamientos cambiando la implementación específica utilizada sin requerir ningún cambio significativo en el código. Los comportamientos también se pueden cambiar en tiempo de ejecución y en tiempo de diseño. Por ejemplo, el comportamiento de frenado de un objeto automóvil se puede cambiar de BrakeWithABS()a Brake()cambiando el brakeBehaviormiembro a:

BrakeBehavior = nuevo freno ();   
/* Familia encapsulada de algoritmos * Interfaz y sus implementaciones */ public interface IBrakeBehavior { public void Brake (); }      La clase pública BrakeWithABS implementa IBrakeBehavior { freno vacío público () { Sistema . afuera . println ( "Freno con ABS aplicado" ); } }           El freno de clase pública implementa IBrakeBehavior { freno vacío público () { Sistema . afuera . println ( "Freno simple aplicado" ); } }           /* Cliente que puede usar los algoritmos anteriores indistintamente */ public abstract class Car { private IBrakeBehavior BrakeBehavior ;        coche público ( IBrakeBehavior BrakeBehavior ) { este . comportamientofreno = comportamientofreno ; }        aplicar freno público vacío () { frenoBehavior . freno (); }      public void setBrakeBehavior ( IBrakeBehavior tipo freno ) { this . comportamientofreno = tipofreno ; } }        /* El cliente 1 usa un algoritmo (Brake) en el constructor */ public class Sedan extends Car { public Sedan () { super ( new Brake ()); } }           /* El cliente 2 usa otro algoritmo (BrakeWithABS) en el constructor */ public class SUV extends Car { public SUV () { super ( new BrakeWithABS ()); } }           /* Usando el ejemplo de Auto */ public class CarExample { public static void main ( final String [] argumentos ) { Car sedanCar = new Sedan (); sedánCoche . aplicar freno (); // Esto invocará la clase "Freno"                  Coche suvCar = SUV nuevo (); todoterreno . aplicar freno (); // Esto invocará la clase "BrakeWithABS"       // establece el comportamiento de los frenos dinámicamente suvCar . setBrakeBehavior ( nuevo freno () ); todoterreno . aplicar freno (); // Esto invocará la clase "Freno" } }       

Ver también

Referencias

  1. ^ "El patrón de diseño de la estrategia: problema, solución y aplicabilidad". w3sDesign.com . Consultado el 12 de agosto de 2017 .
  2. ^ Eric Freeman, Elisabeth Freeman, Kathy Sierra y Bert Bates, Head First Design Patterns , primera edición, capítulo 1, página 24, O'Reilly Media, Inc, 2004. ISBN 978-0-596-00712-6 
  3. ^ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Patrones de diseño: elementos de software reutilizable orientado a objetos . Addison Wesley. págs. 315 y siguientes. ISBN 0-201-63361-2.{{cite book}}: Mantenimiento CS1: varios nombres: lista de autores ( enlace )
  4. ^ "El patrón de diseño de la estrategia: estructura y colaboración". w3sDesign.com . Consultado el 12 de agosto de 2017 .
  5. ^ "Referencia rápida de patrones de diseño: McDonaldLand".

enlaces externos