¿Son las funciones de primera clase un sustituto del patrón de estrategia?

15

El Patrón de diseño de la estrategia a menudo se considera un sustituto de las funciones de primera clase en idiomas que carecen de ellas.

Por ejemplo, digamos que querías pasar la funcionalidad a un objeto. En Java, tendría que pasar en el objeto otro objeto que encapsule el comportamiento deseado. En un lenguaje como Ruby, solo pasaría la funcionalidad en forma de una función anónima.

Sin embargo, lo estaba pensando y decidí que quizás la Estrategia ofrece más que una simple función anónima.

Esto se debe a que un objeto puede mantener el estado que existe independientemente del período en que se ejecuta el método. Sin embargo, una función anónima por sí sola solo puede mantener el estado que deja de existir en el momento en que la función termina de ejecutarse.

En un lenguaje orientado a objetos que admite funciones de primera clase, ¿el patrón de estrategia tiene alguna ventaja sobre el uso de funciones?

    
pregunta Aviv Cohn 16.08.2014 - 13:34
fuente

4 respuestas

13

Cuando el lenguaje admite referencias a la función ( Java lo hace desde la versión 8 ), estas son a menudo una buena alternativa para las estrategias, porque generalmente expresan lo mismo con menos sintaxis. Sin embargo, hay algunos casos en los que un objeto real puede ser útil.

Una interfaz de estrategia puede tener múltiples métodos. Tomemos como ejemplo una interfaz RouteFindingStragegy , que encapsula diferentes algoritmos de búsqueda de rutas. Podría declarar métodos como

  • Route findShortestRoute(Node start, Node destination)
  • boolean doesRouteExist(Node start, Node destination)
  • Route[] findAllPossibleRoutes(Node start, Node destination)
  • Route findShortestRouteToClosestDestination(Node start, Node[] destinations)
  • Route findTravelingSalesmanRoute(Node[] stations)

que entonces todos serían implementados por la estrategia. Algunos algoritmos de búsqueda de rutas podrían permitir optimizaciones internas para algunos de estos casos de uso y otros no, por lo que el implementador puede decidir cómo implementar cada uno de estos métodos.

Otro caso es cuando la estrategia tiene un estado interno. Claro, en algunos idiomas, los cierres pueden tener un estado interno, pero cuando este estado interno se vuelve muy complejo, a menudo se vuelve más elegante promover el cierre a una clase de pleno derecho.

    
respondido por el Philipp 16.08.2014 - 13:55
fuente
5

No es cierto que una función anónima solo pueda mantener el estado que deja de existir cuando la función termina de ejecutarse.

Toma el siguiente ejemplo en Common Lisp:

(defun number-strings (ss)
  (let ((counter 0))
    (mapcar #'(lambda (s) (format nil "~a: ~a" (incf counter) s)) ss)))

Esta función toma una lista de cadenas y antepone un contador a cada elemento de la lista. Así, por ejemplo, invocando

(number-strings '("a" "b" "c"))

da

("1: a" "2: b" "3: c")

La función number-strings usa internamente una función anónima con una variable counter que mantiene el estado (el valor actual del contador) que se reutiliza cada vez que se invoca la función.

En general, puede pensar en un cierre como un objeto con un solo método. Alternativamente, un objeto es una colección de cierres que comparten las mismas variables cerradas. Así que no estoy seguro de si hay casos en los que necesite usar un objeto en lugar de un cierre: yo diría que ambas son formas de ver el mismo patrón desde diferentes perspectivas.

En particular, el patrón de estrategia requiere un objeto con un solo método, por lo que un cierre debe hacer el trabajo. Pero, como Philipp ha observado en su respuesta, dependiendo de las circunstancias (estado complejo) y los lenguajes de programación, puede obtener una solución más elegante utilizando objetos.

    
respondido por el Giorgio 16.08.2014 - 13:49
fuente
1

El hecho de que dos diseños puedan resolver el mismo problema no significa que sean sustituciones directas entre sí.

Si necesita realizar un seguimiento del estado en un programa funcional, no debe mutar una variable cerrada, incluso si el idioma lo permite. Usted organiza la llamada a una función que toma un estado como argumento y devuelve el nuevo estado como su valor de retorno.

Tu arquitectura se verá muy diferente, pero lograrás el mismo objetivo. No intentes forzar los patrones de un paradigma directamente sobre el otro.

    
respondido por el Karl Bielefeldt 17.08.2014 - 18:26
fuente
1

La estrategia es un concepto , una receta útil para resolver un problema particular y recurrente. No es una construcción de lenguaje, ni se trata de ninguna forma de implementación . Se puede utilizar un cierre para implementar la Estrategia un día y el Observador al día siguiente.

El término estrategia es principalmente útil en conversaciones con otros programadores para expresar de manera concisa su intención. No hay nada mágico al respecto.

    
respondido por el idoby 17.08.2014 - 21:47
fuente

Lea otras preguntas en las etiquetas