Le funzioni di prima classe sono un sostituto del modello di strategia?

15

Il schema di progettazione della strategia viene spesso considerato un sostituto delle funzioni di prima classe nelle lingue a cui mancano.

Quindi, ad esempio, dici di voler passare la funzionalità in un oggetto. In Java dovresti passare nell'oggetto un altro oggetto che incapsula il comportamento desiderato. In una lingua come Ruby, passeresti semplicemente la funzionalità stessa sotto forma di una funzione anonima.

Comunque ci stavo pensando e ho deciso che forse la Strategia offre più di una semplice funzione anonima.

Questo perché un oggetto può contenere lo stato che esiste indipendentemente dal periodo in cui viene eseguito il metodo. Tuttavia una funzione anonima di per sé può solo contenere lo stato che cessa di esistere nel momento in cui la funzione termina l'esecuzione.

In un linguaggio orientato agli oggetti che supporta funzioni di prima classe, il modello di strategia ha qualche vantaggio sull'uso delle funzioni?

    
posta Aviv Cohn 16.08.2014 - 13:34
fonte

4 risposte

13

Quando il linguaggio supporta i riferimenti alla funzione ( Java fa dalla versione 8 ), queste sono spesso una buona alternativa per le strategie, perché di solito esprimono la stessa cosa con meno sintassi. Tuttavia, ci sono alcuni casi in cui un oggetto reale può essere utile.

Un'interfaccia strategica può avere più metodi. Prendiamo come esempio un'interfaccia RouteFindingStragegy , che incapsula diversi algoritmi di ricerca del percorso. Potrebbe dichiarare metodi come

  • 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)

che poi sarebbero tutti implementati dalla strategia. Alcuni algoritmi di individuazione dei percorsi potrebbero consentire ottimizzazioni interne per alcuni di questi casi d'uso e alcuni potrebbero non esserlo, quindi l'implementatore può decidere come implementare ciascuno di questi metodi.

Un altro caso è quando la strategia ha uno stato interiore. Certo, in alcune lingue le chiusure possono avere uno stato interiore, ma quando questo stato interno diventa molto complesso, spesso diventa più elegante promuovere la chiusura a una classe a tutti gli effetti.

    
risposta data 16.08.2014 - 13:55
fonte
5

Non è vero che una funzione anonima può contenere solo lo stato che cessa di esistere quando la funzione termina l'esecuzione.

Prendi il seguente esempio in Common Lisp:

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

Questa funzione prende un elenco di stringhe e antepone un contatore a ciascun elemento della lista. Quindi, ad esempio, invocando

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

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

La funzione number-strings utilizza internamente una funzione anonima con una variabile counter che contiene lo stato (il valore corrente del contatore) che viene riutilizzata ogni volta che viene richiamata la funzione.

In generale, puoi pensare a una chiusura come a un oggetto con un solo metodo. In alternativa, un oggetto è una raccolta di chiusure che condividono le stesse variabili chiuse. Quindi non sono sicuro che ci siano casi in cui è necessario utilizzare un oggetto invece di una chiusura: direi che entrambi sono modi di guardare lo stesso modello da diverse prospettive.

In particolare, il modello di strategia richiede un oggetto con un solo metodo, quindi una chiusura dovrebbe fare il lavoro. Ma, come Philipp ha osservato nella sua risposta, a seconda delle circostanze (stato complesso) e dei linguaggi di programmazione, puoi ottenere una soluzione più elegante usando gli oggetti.

    
risposta data 16.08.2014 - 13:49
fonte
1

Solo perché due progetti possono risolvere lo stesso problema non significa che siano sostituzioni dirette l'una per l'altra.

Se è necessario tenere traccia dello stato in un programma funzionale, non si muta una variabile chiusa sopra, anche se la lingua lo consente. Si dispone di chiamare una funzione che accetta uno stato come argomento e restituisce il nuovo stato come valore di ritorno.

La tua architettura apparirà molto diversa, ma realizzerai lo stesso obiettivo. Non cercare di forzare i modelli di un paradigma direttamente sull'altro.

    
risposta data 17.08.2014 - 18:26
fonte
1

La strategia è un concetto , una ricetta utile per risolvere un particolare problema ricorrente. Non è un costrutto linguistico, né riguarda una qualsiasi forma di implementazione . Una chiusura può essere utilizzata per implementare la strategia in un giorno e Observer il giorno successivo.

La strategia termine è utile soprattutto nelle conversazioni con altri programmatori per esprimere in modo conciso le tue intenzioni. Non c'è niente di magico in questo.

    
risposta data 17.08.2014 - 21:47
fonte

Leggi altre domande sui tag