stringtranslate.com

Patrón de estrategia

En programación informática , 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 en tiempo de ejecución sobre cuál de una familia de algoritmos utilizar. [1]

La estrategia permite que el algoritmo varíe independientemente de los clientes que lo utilizan. [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 usar 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 la validación de los datos entrantes puede utilizar el patrón de estrategia para seleccionar un algoritmo de validación en función del tipo de datos, la fuente de los datos, la elección del usuario u otros factores de discriminación. Estos factores no se conocen hasta el tiempo de ejecución y pueden requerir que se realice una validación radicalmente diferente. Los algoritmos de validación (estrategias), 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 sistemas diferentes) sin duplicación de código .

Por lo general, el patrón de estrategia almacena una referencia al código en una estructura de datos y lo recupera. Esto se puede lograr mediante mecanismos como el puntero de función nativo , 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 clases y secuencias UML

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

En el diagrama de clases UML anterior , la clase no implementa un algoritmo directamente. En cambio, se refiere a la interfaz para ejecutar un algoritmo ( ), lo que hace que sea 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 ejecuta el algoritmo y devuelve el resultado a . Luego, cambia su estrategia y llama a un objeto, que ejecuta el algoritmo y devuelve el resultado a .ContextContextStrategystrategy.algorithm()ContextStrategy1Strategy2Strategy
ContextStrategyContextalgorithm()Strategy1ContextContextalgorithm()Strategy2Context

Diagrama de clases

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 nuevo modelo de automóvil .

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

Como ejemplo, considere una clase de automóvil. Dos posibles funcionalidades para automóvil son freno y aceleración . Dado que los comportamientos de aceleración y freno cambian con frecuencia entre modelos, un enfoque común es implementar estos comportamientos en subclases. Este enfoque tiene desventajas significativas; los comportamientos de aceleración y freno deben declararse en cada nuevo modelo de automóvil. El trabajo de gestión de estos comportamientos aumenta enormemente a medida que aumenta el número de modelos y requiere que el código se duplique en todos 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 la composición en lugar de la herencia . En el patrón de estrategia, los comportamientos se definen como interfaces independientes 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 interrumpir las clases que lo utilizan, y las clases pueden cambiar entre comportamientos modificando la implementación específica utilizada sin necesidad de realizar cambios significativos 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 freno de un objeto de automóvil se puede cambiar de BrakeWithABS()a Brake()modificando el brakeBehaviormiembro a:

comportamientoFreno = nuevo Freno ();   
/* Familia encapsulada de algoritmos * Interfaz y sus implementaciones */ public interface IBrakeBehavior { public void brake (); }      clase pública BrakeWithABS implementa IBrakeBehavior { public void brake () { System . println ( "Freno con ABS aplicado " ) ; } }           clase pública Brake implementa IBrakeBehavior { public void brake () { System . println ( "Freno simple aplicado " ) ; } }           /* Cliente que puede utilizar los algoritmos anteriores indistintamente */ public abstract class Car { private IBrakeBehavior brakeBehavior ;        público Coche ( IBrakeBehavior brakeBehavior ) { this . brakeBehavior = brakeBehavior ; }        público void aplicarFreno () { comportamientoFreno.freno ( ) ; }      público void setBrakeBehavior ( IBrakeBehavior brakeType ) { este .brakeBehavior = brakeType ; } }        /* El cliente 1 usa un algoritmo (Freno) 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 Car */ public class CarExample { public static void main ( final String [] arguments ) { Car sedanCar = new Sedan (); sedanCar . applyBrake (); // Esto invocará la clase "Brake"                  Coche suvCar = new SUV (); suvCar.applyBrake (); // Esto invocará la clase " BrakeWithABS "       // establece el comportamiento del freno dinámicamente suvCar . setBrakeBehavior ( new Brake () ); suvCar . applyBrake (); // Esto invocará la clase "Brake" } }       

Véase también

Referencias

  1. ^ "El patrón de diseño de 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. pp. 315ff. ISBN 0-201-63361-2.{{cite book}}: CS1 maint: varios nombres: lista de autores ( enlace )
  4. ^ "El patrón de diseño de 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