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 .
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 .Context
Context
Strategy
strategy.algorithm()
Context
Strategy1
Strategy2
Strategy
Context
Strategy
Context
algorithm()
Strategy1
Context
Context
algorithm()
Strategy2
Context
[5]
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 brakeBehavior
miembro 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" } }
{{cite book}}
: CS1 maint: varios nombres: lista de autores ( enlace )