2009-06-08 12 views
9

Nel solito schema di strategia, facciamo ogni strategia come una classe. Non possiamo renderlo una funzione, e basta assegnare il riferimento alla funzione quando istanziamo un oggetto e lascia che l'oggetto chiami quella funzione?In Strategy Pattern, non possiamo rendere ogni strategia come una funzione ma non come una classe?

+0

Divertiti con Java in questo caso :) – Joey

+1

perché? Java non supporta il riferimento alla funzione? –

+7

+1 per pensare in modo critico a Design Patterns. Direi che molti modelli di design derivano dalla radice dell'incapacità della lingua. Quindi in molti casi, i modelli di progettazione non sono bibbie :) – kizzx2

risposta

3

Nei casi più semplici, è possibile sostituire i modelli di strategia con un puntatore a funzione. Tuttavia, considerare questo caso

class HourlyPayStrategy implements PayStrategy 
{ 
    public int calculate() 
    { 
     int x = doComplexOperation1(); 
     int y = doComplexOperation2(); 

     return x + y; 
    } 

    private int doComplexOperation1() 
    { 
     // ... 
    } 

    private int doComplexOperation2() 
    { 
     // ... 
    } 
} 

Se abbiamo appena dato un semplice puntatore a funzione, le cose iniziano diventando davvero pelose, perché non è più possibile refactoring quella cosa (beh, almeno non in modo ben incapsulata).

+0

Non sono d'accordo. Se fai riferimento a HourlyPayStrategy o HourlyPayStrategy.calculate non fa differenza in termini di refactoring o incapsulamento. –

+0

@DavidArno con la tua notazione Credo che tu conosca C#, che fa un buon lavoro eseguendo _eta expansion_. Questa notazione non è affatto facile da ottenere in molte lingue: JavaScript, Ruby, Python, Java, OCaml anche (parlando da una memoria vecchia di anni), C++ (domande: come si ciba ora C++ 11 al giorno d'oggi?). – kizzx2

+0

In molte lingue, quando ci si aspetta un parametro _function_ come parametro, è abbastanza diverso da aspettarsi un _method_, dove il compilatore/runtime dovrebbe portare con sé l'oggetto associato. Quindi sì, per C# il tuo argomento ha le gambe. – kizzx2

4

Dipende dalla lingua. In C# potresti renderlo un delegato. In Java, sarebbe piuttosto una classe anonima. In C++, potresti davvero renderlo un puntatore a funzione.

2

Certo, anche se utilizzando gli oggetti è possibile sfruttare l'ereditarietà in modi che non si possono ottenere con le sole funzioni.

1

In C# è possibile utilizzare i delegati con il modello di strategia. Date un'occhiata a questo blog post per un esempio.

1

Cosa succede sotto il cofano nella maggior parte delle implementazioni C++ è quasi quello che suggerisci. Il compilatore di solito risolve una Strategy.virtualMethod call() come questo (in pseudo codice):

 
    (Strategy.pVtable[indexOfVirtualMethod])() 

Quindi, se la vostra unica preoccupazione è quella più dereferenziazione di un puntatore (pVtable) si dovrebbe davvero profilo in primo luogo se non è possibile identificare gli hotspot più gravi.

La mia sensazione è che il codice sarà molto più difficile da capire e mantenere quando si utilizza un puntatore a funzione invece di un oggetto strategia.

Problemi correlati