Articulo de referencia

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 conductual que permite seleccionar un algori...

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 conductual 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. Posponer la decisión sobre qué algoritmo usar hasta el tiempo de ejecución permite que el código que lo llama sea más flexible y reutilizable.

Por ejemplo, una clase que realiza la validación de datos entrantes puede usar el patrón de estrategia para seleccionar un algoritmo de validación según el tipo de datos, su origen, la elección del usuario u otros factores discriminatorios. Estos factores no se conocen hasta el tiempo de ejecución y pueden requerir una validación radicalmente diferente. Los algoritmos de validación (estrategias), encapsulados por separado del objeto que realiza la validación, pueden ser utilizados por otros objetos de validación en diferentes áreas del sistema (o incluso en sistemas distintos) 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 a función nativo , la función de primera clase , las 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 mediante reflexión .

Estructura

Diagrama de clases y secuencia UML

Un ejemplo de diagrama de clases 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 realizar un algoritmo ( ), lo que 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 . Posteriormente, cambia su estrategia y llama a un objeto, que realiza el algoritmo y devuelve el resultado a .ContextContextStrategystrategy.algorithm()ContextStrategy1Strategy2StrategyContextStrategyContextalgorithm()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 deben heredarse. En su lugar, deben encapsularse mediante interfaces. Esto es compatible con el principio de abierto-cerrado (OCP), que propone que las clases deben ser abiertas a la extensión pero cerradas a la modificación.

Por ejemplo, consideremos la clase `coche`. Dos funcionalidades posibles para este modelo son frenar y acelerar . Dado que el comportamiento de aceleración y frenado varía con frecuencia entre modelos, una estrategia común consiste en implementarlo en subclases. Sin embargo, este enfoque presenta inconvenientes importantes: el comportamiento de aceleración y frenado debe declararse en cada nuevo modelo de coche. La gestión de este comportamiento se incrementa considerablemente a medida que aumenta el número de modelos y requiere la duplicación de código. Además, resulta difícil determinar la naturaleza exacta del comportamiento de cada modelo sin analizar su código.

El patrón de estrategia utiliza composición en lugar de herencia . En este patrón, los comportamientos se definen como interfaces separadas y clases específicas que implementan dichas interfaces. Esto permite un mejor desacoplamiento entre el comportamiento y la clase que lo utiliza. El comportamiento puede modificarse sin afectar a las clases que lo utilizan, y estas pueden alternar entre comportamientos cambiando la implementación específica sin necesidad de realizar cambios significativos en el código. Los comportamientos también pueden modificarse tanto en tiempo de ejecución como en tiempo de diseño. Por ejemplo, el comportamiento de frenado de un objeto "coche" puede cambiarse BrakeWithABS()modificando Brake()el brakeBehaviormiembro a:

Freno * comportamiento de frenado = nuevo Freno ();
paquete org.wikipedia.examples ;/* Familia encapsulada de algoritmos * Interfaz y sus implementaciones */ interface IBrakeBehavior { public void brake (); }class BrakeWithABS implements IBrakeBehavior { public void brake () { System . out . println ( "Frenado con ABS aplicado" ); } }class Brake implements IBrakeBehavior { public void brake () { System . out . println ( "Freno simple aplicado" ); } }// Cliente que puede usar los algoritmos anteriores indistintamente clase abstracta Car { private IBrakeBehavior brakeBehavior ;public Car ( IBrakeBehavior brakeBehavior ) { this . brakeBehavior = brakeBehavior ; }public void applyBrake () { brakeBehavior . brake (); }public void setBrakeBehavior ( IBrakeBehavior tipo freno ) { this . comportamientofreno = tipofreno ; } }// El cliente 1 utiliza un algoritmo (Brake) en el constructor. class Sedan extends Car { public Sedan () { super ( new Brake ()); } }// El cliente 2 utiliza otro algoritmo (BrakeWithABS) en el constructor. La clase SUV extiende Car { public SUV () { super ( new BrakeWithABS ()); } }// Usando el ejemplo Car public class CarExample { public static void main ( String [] arguments ) { Car sedanCar = new Sedan (); sedanCar . applyBrake (); // Esto invocará la clase "Brake"Coche suvCar = nuevo SUV (); suvCar . applyBrake (); // Esto invocará la clase "BrakeWithABS"// Establecer 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 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 orientado a objetos reutilizable . Addison Wesley. pp. 315 y ss . ISBN  0-201-63361-2.{{cite book}}: CS1 maint: varios nombres: lista de autores ( enlace )
  4. "El patrón de diseño Estrategia: Estructura y Colaboración" . w3sDesign.com . Consultado el 12 de agosto de 2017 .
  5. "Referencia rápida de patrones de diseño – McDonaldLand" .
  • Patrón de estrategia en UML (en español)
  • Geary, David (26 de abril de 2002). "Estrategia para el éxito" . Patrones de diseño de Java. JavaWorld . Recuperado el 20 de julio de 2020 .
  • Patrón de estrategia para el artículo C
  • Refactorización: Reemplazar el código de tipo con estado/estrategia.
  • El patrón de diseño Strategy en Wayback Machine (archivado el 15/04/2017) Implementación del patrón Strategy en JavaScript